Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/cxxalloc.h
Warning:line 42, column 10
Value of 'errno' was not checked and may be overwritten by function 'moz_xmalloc'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name nsAppRunner.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/toolkit/xre -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/toolkit/xre -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -D _GLIBCXX_ASSERTIONS=1 -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D TELEMETRY_PING_FORMAT_VERSION=4 -D PROXY_PRINTING=1 -D USE_GLX_TEST -D MOZ_APP_NAME="firefox" -D MOZ_APP_BASENAME="Firefox" -D MOZ_APP_DISPLAYNAME="Nightly" -D MOZ_APP_VENDOR="Mozilla" -D MOZ_APP_VERSION="160.0a1" -D OS_TARGET="Linux" -D MOZ_WIDGET_TOOLKIT="gtk" -D MOZ_UPDATER -D MOZ_DISTRIBUTION_ID="org.mozilla" -D TARGET_OS_ABI="Linux_x86_64-gcc3" -D GRE_MILESTONE=160.0a1 -D MOZ_APP_VERSION_DISPLAY=160.0a1 -D APP_VERSION=160.0a1 -D APP_ID={ec8030f7-c20a-464f-9b0e-13a3a9e97384} -D MOZ_BUILD_APP_IS_BROWSER -D MAR_NSS -D TOPOBJDIR=/root/firefox-clang/obj-x86_64-pc-linux-gnu -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/toolkit/xre -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/toolkit/xre -I /root/firefox-clang/toolkit/components/remote -I /root/firefox-clang/widget -I /root/firefox-clang/widget/gtk -I /root/firefox-clang/toolkit/components/printingui -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /root/firefox-clang/ipc/chromium/src -I /root/firefox-clang/third_party/abseil-cpp -I /root/firefox-clang/other-licenses/nsis/Contrib/CityHash/cityhash -I /root/firefox-clang/toolkit/components/find -I /root/firefox-clang/toolkit/components/printingui/ipc -I /root/firefox-clang/toolkit/components/windowwatcher -I /root/firefox-clang/toolkit/mozapps/update/common -I /root/firefox-clang/toolkit/profile -I /root/firefox-clang/config -I /root/firefox-clang/dom/base -I /root/firefox-clang/dom/commandhandler -I /root/firefox-clang/dom/ipc -I /root/firefox-clang/dom/webbrowserpersist -I /root/firefox-clang/js/xpconnect/loader -I /root/firefox-clang/testing/gtest/mozilla -I /root/firefox-clang/third_party/sqlite3/ext -I /root/firefox-clang/toolkit/components/jsoncpp/include -I /root/firefox-clang/toolkit/crashreporter -I /root/firefox-clang/xpcom/build -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/uuid -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/gtk-3.0/unix-print -I /usr/include/gtk-3.0 -I /usr/include/pango-1.0 -I /usr/include/cloudproviders -I /usr/include/at-spi2-atk/2.0 -I /usr/include/at-spi-2.0 -I /usr/include/dbus-1.0 -I /usr/lib/x86_64-linux-gnu/dbus-1.0/include -I /usr/include/fribidi -I /usr/include/harfbuzz -I /usr/include/atk-1.0 -I /usr/include/cairo -I /usr/include/pixman-1 -I /usr/include/gdk-pixbuf-2.0 -I /usr/include/glycin-2 -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/gio-unix-2.0 -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/sysprof-6 -I /usr/include/pango-1.0 -I /usr/include/harfbuzz -I /usr/include/glib-2.0 -I /usr/lib/x86_64-linux-gnu/glib-2.0/include -I /usr/include/libmount -I /usr/include/blkid -I /usr/include/fribidi -I /usr/include/cairo -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/pixman-1 -I /usr/include/sysprof-6 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/x86_64-linux-gnu/c++/16 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/backward -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=pessimizing-move -Wno-error=large-by-value-copy=128 -Wno-error=implicit-int-float-conversion -Wno-error=thread-safety-analysis -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -Wno-character-conversion -std=gnu++20 -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-implicit-modules -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-10-17-231001-351276-1 -x c++ /root/firefox-clang/toolkit/xre/nsAppRunner.cpp

/root/firefox-clang/toolkit/xre/nsAppRunner.cpp

→
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#include "mozilla/dom/ContentParent.h"
6#include "mozilla/dom/ContentChild.h"
7#include "mozilla/ipc/GeckoChildProcessHost.h"
8
9#include "mozilla/AppShutdown.h"
10#include "mozilla/Assertions.h"
11#include "mozilla/Attributes.h"
12#include "mozilla/BaseProfiler.h"
13#include "mozilla/Components.h"
14#include "mozilla/FilePreferences.h"
15#include "mozilla/FOG.h"
16#include "mozilla/ChaosMode.h"
17#include "mozilla/HelperMacros.h"
18#include "mozilla/CmdLineAndEnvUtils.h"
19#include "mozilla/IOInterposer.h"
20#include "mozilla/ipc/UtilityProcessChild.h"
21#include "mozilla/Likely.h"
22#include "mozilla/Logging.h"
23#include "mozilla/Preferences.h"
24#include "mozilla/PreferenceSheet.h"
25#include "mozilla/Printf.h"
26#include "mozilla/ProcessType.h"
27#include "mozilla/ResultExtensions.h"
28#include "mozilla/RuntimeExceptionModule.h"
29#include "mozilla/FileUtils.h"
30#include "mozilla/ScopeExit.h"
31#include "mozilla/StaticPrefs_browser.h"
32#include "mozilla/StaticPrefs_fission.h"
33#include "mozilla/StaticPrefs_security.h"
34#include "mozilla/StaticPrefs_widget.h"
35#include "mozilla/glean/SecuritySandboxMetrics.h"
36#include "mozilla/Telemetry.h"
37#include "mozilla/Try.h"
38#include "mozilla/intl/LocaleService.h"
39#include "mozilla/JSONWriter.h"
40#include "mozilla/gfx/gfxVars.h"
41#include "mozilla/glean/ToolkitMozappsUpdateSharedMetrics.h"
42#include "mozilla/glean/ToolkitXreMetrics.h"
43#include "mozilla/glean/GleanPings.h"
44#include "mozilla/widget/TextRecognition.h"
45#include "mozJSModuleLoader.h"
46
47#include "nsAppRunner.h"
48#include "mozilla/XREAppData.h"
49#include "mozilla/Bootstrap.h"
50#if defined(MOZ_UPDATER1) && !defined(MOZ_WIDGET_ANDROID)
51# include "nsUpdateDriver.h"
52# include "nsUpdateSyncManager.h"
53#endif
54#include "ProfileReset.h"
55
56#ifdef XP_MACOSX
57# include "nsVersionComparator.h"
58# include "nsCocoaFeatures.h"
59# include "mozilla/glean/WidgetCocoaMetrics.h"
60# include "MacLaunchHelper.h"
61# include "MacApplicationDelegate.h"
62# include "MacAutoreleasePool.h"
63# include "MacRunFromDmgUtils.h"
64# include "ASWebAuthSessionHandler.h"
65// these are needed for sysctl
66# include <sys/types.h>
67# include <sys/sysctl.h>
68#endif
69
70#include "prnetdb.h"
71#include "prprf.h"
72#include "prproces.h"
73#include "prenv.h"
74#include "prtime.h"
75
76#include "nsIAppStartup.h"
77#include "nsCategoryManagerUtils.h"
78#include "nsIMutableArray.h"
79#include "nsCommandLine.h"
80#include "nsIComponentRegistrar.h"
81#include "nsIDialogParamBlock.h"
82#include "mozilla/ModuleUtils.h"
83#include "nsIIOService.h"
84#include "nsIObserverService.h"
85#include "nsINativeAppSupport.h"
86#include "nsIPlatformInfo.h"
87#include "nsIProcess.h"
88#include "nsIProfileUnlocker.h"
89#include "nsIPromptService.h"
90#include "nsIPropertyBag2.h"
91#include "nsIServiceManager.h"
92#include "nsIStringBundle.h"
93#include "nsISupportsPrimitives.h"
94#include "nsIToolkitProfile.h"
95#include "nsToolkitProfileService.h"
96#include "nsIURI.h"
97#include "nsIURL.h"
98#include "nsIWindowCreator.h"
99#include "nsIWindowWatcher.h"
100#include "nsIXULAppInfo.h"
101#include "nsIXULRuntime.h"
102#include "nsPIDOMWindow.h"
103#include "nsIWidget.h"
104#include "nsAppShellCID.h"
105#include "mozilla/dom/quota/QuotaManager.h"
106#include "mozilla/scache/StartupCache.h"
107#include "gfxPlatform.h"
108#include "PDMFactory.h"
109#ifdef XP_MACOSX
110# include "gfxPlatformMac.h"
111#endif
112
113#ifdef XP_WIN
114# include "nsIWinAppHelper.h"
115# include <windows.h>
116# include <intrin.h>
117# include <math.h>
118# include "cairo/cairo-features.h"
119# include "mozilla/PreXULSkeletonUI.h"
120# include "mozilla/DllPrefetchExperimentRegistryInfo.h"
121# include "mozilla/WindowsDllBlocklist.h"
122# include "mozilla/WindowsMsctfInitialization.h"
123# include "mozilla/WindowsOleAut32Initialization.h"
124# include "mozilla/WindowsProcessMitigations.h"
125# include "mozilla/WindowsVersion.h"
126# include "mozilla/WinHeaderOnlyUtils.h"
127# include "mozilla/mscom/ProcessRuntime.h"
128# include "mozilla/mscom/ProfilerMarkers.h"
129# include "WinTokenUtils.h"
130
131# if defined(MOZ_LAUNCHER_PROCESS)
132# include "mozilla/LauncherRegistryInfo.h"
133# endif
134
135# if defined(MOZ_DEFAULT_BROWSER_AGENT)
136# include "nsIWindowsRegKey.h"
137# endif
138
139# ifndef PROCESS_DEP_ENABLE
140# define PROCESS_DEP_ENABLE 0x1
141# endif
142#endif
143
144#if defined(MOZ_SANDBOX1)
145# include "mozilla/SandboxSettings.h"
146#endif
147
148#ifdef ACCESSIBILITY1
149# include "nsAccessibilityService.h"
150# include "mozilla/a11y/Platform.h"
151# if defined(XP_WIN)
152# include "mozilla/a11y/Compatibility.h"
153# endif
154#endif
155
156#include "json/json.h"
157#include "nsCRT.h"
158#include "nsCOMPtr.h"
159#include "nsDirectoryServiceDefs.h"
160#include "nsDirectoryServiceUtils.h"
161#include "nsEmbedCID.h"
162#include "nsIDUtils.h"
163#include "nsNetUtil.h"
164#include "nsReadableUtils.h"
165#include "nsXPCOM.h"
166#include "nsXPCOMCIDInternal.h"
167#include "nsString.h"
168#include "nsPrintfCString.h"
169#include "nsVersionComparator.h"
170
171#include "nsAppDirectoryServiceDefs.h"
172#include "nsXULAppAPI.h"
173#include "nsXREDirProvider.h"
174
175#include "nsINIParser.h"
176#include "mozilla/Omnijar.h"
177#include "mozilla/StartupTimeline.h"
178#include "mozilla/LateWriteChecks.h"
179
180#include <stdlib.h>
181#include <string_view>
182
183#ifdef XP_UNIX1
184# include <errno(*__errno_location ()).h>
185# include <pwd.h>
186# include <string.h>
187# include <sys/resource.h>
188# include <sys/stat.h>
189# include <unistd.h>
190#endif
191
192#ifdef XP_WIN
193# include <process.h>
194# include <shlobj.h>
195# include "mozilla/WinDllServices.h"
196# include "nsThreadUtils.h"
197# include "WinUtils.h"
198#endif
199
200#ifdef XP_MACOSX
201# include "nsILocalFileMac.h"
202# include "nsCommandLineServiceMac.h"
203#endif
204
205// for X remote support
206#if defined(MOZ_HAS_REMOTE1)
207# include "nsRemoteService.h"
208#endif
209
210#if defined(DEBUG1) && defined(XP_WIN)
211# include <malloc.h>
212#endif
213
214#if defined(XP_MACOSX)
215# include <Carbon/Carbon.h>
216#endif
217
218#ifdef DEBUG1
219# include "mozilla/Logging.h"
220# include "mozilla/StaticPrefs_toolkit.h"
221#endif
222
223#include "nsExceptionHandler.h"
224#include "nsICrashReporter.h"
225#include "nsIPrefService.h"
226#include "nsIMemoryInfoDumper.h"
227#include "js/String.h"
228#if defined(XP_LINUX1) && !defined(ANDROID)
229# include "mozilla/widget/LSBUtils.h"
230#endif
231
232#include "base/command_line.h"
233#include "GTestRunner.h"
234
235#ifdef MOZ_WIDGET_ANDROID
236# include "gfxAndroidPlatform.h"
237# include "mozilla/java/GeckoAppShellWrappers.h"
238#endif
239
240#if defined(MOZ_SANDBOX1)
241# if defined(XP_LINUX1) && !defined(ANDROID)
242# include "mozilla/SandboxInfo.h"
243# elif defined(XP_WIN)
244# include "sandboxBroker.h"
245# endif
246#endif
247
248#ifdef MOZ_CODE_COVERAGE
249# include "mozilla/CodeCoverageHandler.h"
250#endif
251
252#include "GMPProcessChild.h"
253#include "SafeMode.h"
254
255#ifdef MOZ_BACKGROUNDTASKS1
256# include "mozilla/BackgroundTasks.h"
257# include "nsIPowerManagerService.h"
258# include "nsIStringBundle.h"
259#endif
260
261#ifdef USE_GLX_TEST1
262# include "mozilla/GUniquePtr.h"
263# include "mozilla/GfxInfo.h"
264#endif
265
266#ifdef MOZ_WIDGET_GTK1
267# include "nsAppShell.h"
268#endif
269#ifdef MOZ_ENABLE_DBUS1
270# include "DBusService.h"
271#endif
272
273extern void InstallSignalHandlers(const char* ProgramName);
274
275#define FILE_COMPATIBILITY_INFO"compatibility.ini"_ns "compatibility.ini"_ns
276#define FILE_INVALIDATE_CACHES".purgecaches"_ns ".purgecaches"_ns
277#define FILE_STARTUP_INCOMPLETEu".startup-incomplete"_ns u".startup-incomplete"_ns
278
279#if defined(MOZ_BLOCK_PROFILE_DOWNGRADE1) || defined(MOZ_LAUNCHER_PROCESS) || \
280 defined(MOZ_DEFAULT_BROWSER_AGENT)
281static const char kPrefHealthReportUploadEnabled[] =
282 "datareporting.healthreport.uploadEnabled";
283#endif // defined(MOZ_BLOCK_PROFILE_DOWNGRADE) || defined(MOZ_LAUNCHER_PROCESS)
284 // || defined(MOZ_DEFAULT_BROWSER_AGENT)
285#if defined(MOZ_DEFAULT_BROWSER_AGENT)
286static const char kPrefDefaultAgentEnabled[] = "default-browser-agent.enabled";
287
288static const char kPrefServicesSettingsServer[] = "services.settings.server";
289static const char kPrefSetDefaultBrowserUserChoicePref[] =
290 "browser.shell.setDefaultBrowserUserChoice";
291#endif // defined(MOZ_DEFAULT_BROWSER_AGENT)
292
293#if defined(XP_WIN)
294static const char kPrefThemeId[] = "extensions.activeThemeID";
295# if defined(MOZ_DEFAULT_BROWSER_AGENT)
296static const char kPrefBrowserStartupBlankWindow[] =
297 "browser.startup.blankWindow";
298static const char kPrefPreXulSkeletonUI[] = "browser.startup.preXulSkeletonUI";
299# endif // defined(MOZ_DEFAULT_BROWSER_AGENT)
300#endif // defined(XP_WIN)
301
302#if defined(MOZ_WIDGET_GTK1)
303constexpr nsLiteralCString kStartupTokenNames[] = {
304 "XDG_ACTIVATION_TOKEN"_ns,
305 "DESKTOP_STARTUP_ID"_ns,
306};
307#endif
308
309int gArgc;
310char** gArgv;
311
312static const char gToolkitVersion[] = MOZ_STRINGIFY(GRE_MILESTONE)"160.0a1";
313// The gToolkitBuildID global is defined to MOZ_BUILDID via gen_buildid.py
314// in toolkit/library. See related comment in toolkit/library/moz.build.
315extern const char gToolkitBuildID[];
316
317static nsIProfileLock* gProfileLock;
318#if defined(MOZ_HAS_REMOTE1)
319constinit static RefPtr<nsRemoteService> gRemoteService;
320constinit static RefPtr<nsStartupLock> gStartupLock;
321#endif
322
323int gRestartArgc;
324char** gRestartArgv;
325
326// If gRestartedByOS is set, we were automatically restarted by the OS.
327bool gRestartedByOS = false;
328
329bool gIsGtest = false;
330
331bool gKioskMode = false;
332int gKioskMonitor = -1;
333
334bool gAllowContentAnalysisArgPresent = false;
335
336constinit nsString gAbsoluteArgv0Path;
337
338#if defined(XP_WIN)
339constinit nsString gProcessStartupShortcut;
340#endif
341
342#if defined(MOZ_WIDGET_GTK1)
343# include <glib.h>
344# include "mozilla/WidgetUtilsGtk.h"
345# include <gtk/gtk.h>
346# ifdef MOZ_WAYLAND1
347# include <gdk/gdkwayland.h>
348# include "mozilla/widget/nsWaylandDisplay.h"
349# include "wayland-proxy.h"
350# endif
351# ifdef MOZ_X111
352# include <gdk/gdkx.h>
353# endif /* MOZ_X11 */
354#endif
355
356#if defined(MOZ_WAYLAND1)
357constinit std::unique_ptr<WaylandProxy> gWaylandProxy;
358#endif
359
360#include "BinaryPath.h"
361
362#ifdef FUZZING
363# include "FuzzerRunner.h"
364
365namespace mozilla {
366FuzzerRunner* fuzzerRunner = 0;
367} // namespace mozilla
368
369# ifdef LIBFUZZER
370void XRE_LibFuzzerSetDriver(LibFuzzerDriver aDriver) {
371 mozilla::fuzzerRunner->setParams(aDriver);
372}
373# endif
374#endif // FUZZING
375
376// Undo X11/X.h's definition of None
377#undef None
378
379namespace mozilla {
380int (*RunGTest)(int*, char**) = nullptr;
381
382bool RunningGTest() { return RunGTest; }
383} // namespace mozilla
384
385using namespace mozilla;
386using namespace mozilla::widget;
387using namespace mozilla::startup;
388using mozilla::dom::ContentChild;
389using mozilla::dom::ContentParent;
390using mozilla::dom::quota::QuotaManager;
391using mozilla::intl::LocaleService;
392using mozilla::scache::StartupCache;
393
394#ifndef XP_WIN
395// Save the given word to the specified environment variable.
396static void MOZ_NEVER_INLINE__attribute__((noinline)) SaveWordToEnv(const char* name,
397 const nsACString& word) {
398 char* expr =
399 Smprintf("%s=%s", name, PromiseFlatCStringTPromiseFlatString<char>(word).get()).release();
400 if (expr) PR_SetEnv(expr);
401 // We intentionally leak |expr| here since it is required by PR_SetEnv.
402}
403#endif
404
405// Save the path of the given file to the specified environment variable.
406static void SaveFileToEnv(const char* name, nsIFile* file) {
407#ifdef XP_WIN
408 nsAutoString path;
409 file->GetPath(path);
410 SetEnvironmentVariableW(NS_ConvertASCIItoUTF16(name).get(), path.get());
411#else
412 nsAutoCString path;
413 file->GetNativePath(path);
414 SaveWordToEnv(name, path);
415#endif
416}
417
418static bool gIsExpectedExit = false;
419
420void MozExpectedExit() { gIsExpectedExit = true; }
421
422/**
423 * Runs atexit() to catch unexpected exit from 3rd party libraries like the
424 * Intel graphics driver calling exit in an error condition. When they
425 * call exit() to report an error we won't shutdown correctly and wont catch
426 * the issue with our crash reporter.
427 */
428static void UnexpectedExit() {
429 if (!gIsExpectedExit) {
430 gIsExpectedExit = true; // Don't risk re-entrency issues when crashing.
431 MOZ_CRASH("Exit called by third party code.")do { do { } while (false); MOZ_ReportCrash("" "Exit called by third party code."
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 431); AnnotateMozCrashReason
("MOZ_CRASH(" "Exit called by third party code." ")"); do { MOZ_CrashSequence
(__null, 431); __attribute__((nomerge)) ::abort(); } while (false
); } while (false)
;
432 }
433}
434
435#if defined(MOZ_WAYLAND1)
436bool IsWaylandEnabled() {
437 static bool isWaylandEnabled = []() {
438 const char* waylandDisplay = PR_GetEnv("WAYLAND_DISPLAY");
439 if (!waylandDisplay) {
440 return false;
441 }
442 if (!PR_GetEnv("DISPLAY")) {
443 // No X11 display, so try to run wayland.
444 return true;
445 }
446 // MOZ_ENABLE_WAYLAND is our primary Wayland on/off switch.
447 if (const char* waylandPref = PR_GetEnv("MOZ_ENABLE_WAYLAND")) {
448 return *waylandPref == '1';
449 }
450 if (const char* backendPref = PR_GetEnv("GDK_BACKEND")) {
451 if (!strncmp(backendPref, "wayland", 7)) {
452 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Wayland backend should be enabled by MOZ_ENABLE_WAYLAND=1."
"GDK_BACKEND is a Gtk3 debug variable and may cause issues."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
454)
453 "Wayland backend should be enabled by MOZ_ENABLE_WAYLAND=1."NS_DebugBreak(NS_DEBUG_WARNING, "Wayland backend should be enabled by MOZ_ENABLE_WAYLAND=1."
"GDK_BACKEND is a Gtk3 debug variable and may cause issues."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
454)
454 "GDK_BACKEND is a Gtk3 debug variable and may cause issues.")NS_DebugBreak(NS_DEBUG_WARNING, "Wayland backend should be enabled by MOZ_ENABLE_WAYLAND=1."
"GDK_BACKEND is a Gtk3 debug variable and may cause issues."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
454)
;
455 return true;
456 }
457 }
458 // Enable by default when we're running on a recent enough GTK version. We'd
459 // like to check further details like compositor version and so on ideally
460 // to make sure we don't enable it on old Mutter or what not, but we can't,
461 // so let's assume that if the user is running on a Wayland session by
462 // default we're ok, since either the distro has enabled Wayland by default,
463 // or the user has gone out of their way to use Wayland.
464 return !gtk_check_version(3, 24, 30);
465 }();
466 return isWaylandEnabled;
467}
468#else
469bool IsWaylandEnabled() { return false; }
470#endif
471
472/**
473 * Output a string to the user. This method is really only meant to be used to
474 * output last-ditch error messages designed for developers NOT END USERS.
475 *
476 * @param isError
477 * Pass true to indicate severe errors.
478 * @param fmt
479 * printf-style format string followed by arguments.
480 */
481static MOZ_FORMAT_PRINTF(2, 3)__attribute__((format(printf, 2, 3))) void Output(bool isError, const char* fmt, ...) {
482 va_list ap;
483 va_start(ap, fmt)__builtin_va_start(ap, fmt);
484
485#if defined(XP_WIN) && !MOZ_WINCONSOLE
486 SmprintfPointer msg = mozilla::Vsmprintf(fmt, ap);
487 if (msg) {
488 UINT flags = MB_OK;
489 if (isError)
490 flags |= MB_ICONERROR;
491 else
492 flags |= MB_ICONINFORMATION;
493
494 wchar_t wide_msg[1024];
495 MultiByteToWideChar(CP_ACP, 0, msg.get(), -1, wide_msg,
496 sizeof(wide_msg) / sizeof(wchar_t));
497
498 wchar_t wide_caption[128];
499 MultiByteToWideChar(CP_ACP, 0, gAppData ? gAppData->name : "XULRunner", -1,
500 wide_caption, sizeof(wide_caption) / sizeof(wchar_t));
501 MessageBoxW(nullptr, wide_msg, wide_caption, flags);
502 }
503#elif defined(MOZ_WIDGET_ANDROID)
504 SmprintfPointer msg = mozilla::Vsmprintf(fmt, ap);
505 if (msg) {
506 __android_log_print(isError ? ANDROID_LOG_ERROR : ANDROID_LOG_INFO,
507 "GeckoRuntime", "%s", msg.get());
508 }
509#else
510 vfprintf(stderrstderr, fmt, ap);
511#endif
512
513 va_end(ap)__builtin_va_end(ap);
514}
515
516/**
517 * Check for a commandline flag. If the flag takes a parameter, the
518 * parameter is returned in aParam. Flags may be in the form -arg or
519 * --arg (or /arg on win32).
520 *
521 * @param aArg the parameter to check. Must be lowercase.
522 * @param aParam if non-null, the -arg <data> will be stored in this pointer.
523 * This is *not* allocated, but rather a pointer to the argv data.
524 * @param aFlags flags @see CheckArgFlag
525 */
526static ArgResult CheckArg(const char* aArg, const char** aParam = nullptr,
527 CheckArgFlag aFlags = CheckArgFlag::RemoveArg) {
528 MOZ_ASSERT(gArgv, "gArgv must be initialized before CheckArg()")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gArgv)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(gArgv))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("gArgv" " (" "gArgv must be initialized before CheckArg()"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 528)
; AnnotateMozCrashReason("MOZ_ASSERT" "(" "gArgv" ") (" "gArgv must be initialized before CheckArg()"
")"); do { MOZ_CrashSequence(__null, 528); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
529 return CheckArg(gArgc, gArgv, aArg, aParam, aFlags);
530}
531
532/**
533 * Check for a commandline flag. Ignore data that's passed in with the flag.
534 * Flags may be in the form -arg or --arg (or /arg on win32).
535 * Will not remove flag if found.
536 *
537 * @param aArg the parameter to check. Must be lowercase.
538 */
539static ArgResult CheckArgExists(const char* aArg) {
540 return CheckArg(aArg, nullptr, CheckArgFlag::None);
541}
542
543bool gSafeMode = false;
544bool gFxREmbedded = false;
545
546enum E10sStatus {
547 kE10sEnabledByDefault,
548 kE10sForceDisabled,
549};
550
551static bool gBrowserTabsRemoteAutostart = false;
552static E10sStatus gBrowserTabsRemoteStatus;
553static bool gBrowserTabsRemoteAutostartInitialized = false;
554
555namespace mozilla {
556
557bool BrowserTabsRemoteAutostart() {
558 if (gBrowserTabsRemoteAutostartInitialized) {
559 return gBrowserTabsRemoteAutostart;
560 }
561 gBrowserTabsRemoteAutostartInitialized = true;
562
563 // If we're not in the parent process, we are running E10s.
564 if (!XRE_IsParentProcess()) {
565 gBrowserTabsRemoteAutostart = true;
566 return gBrowserTabsRemoteAutostart;
567 }
568
569 gBrowserTabsRemoteAutostart = true;
570 E10sStatus status = kE10sEnabledByDefault;
571
572// We are checking to ensure that either MOZILLA_OFFICIAL is undefined or that
573// xpc::AreNonLocalConnectionsDisabled() is true. If either check matches,
574// we move on to check the MOZ_FORCE_DISABLE_E10S environment variable which
575// must equal "1" to proceed with disabling e10s.
576#if defined(MOZILLA_OFFICIAL)
577 bool allowDisablingE10s = xpc::AreNonLocalConnectionsDisabled();
578#else
579 bool allowDisablingE10s = true;
580#endif
581
582 if (gBrowserTabsRemoteAutostart && allowDisablingE10s) {
583 const char* forceDisable = PR_GetEnv("MOZ_FORCE_DISABLE_E10S");
584 if (forceDisable && !strcmp(forceDisable, "1")) {
585 gBrowserTabsRemoteAutostart = false;
586 status = kE10sForceDisabled;
587 }
588 }
589
590 gBrowserTabsRemoteStatus = status;
591
592 return gBrowserTabsRemoteAutostart;
593}
594
595} // namespace mozilla
596
597// Win32k Infrastructure ==============================================
598
599// This bool tells us if we have initialized the following two statics
600// upon startup.
601
602static bool gWin32kInitialized = false;
603
604// Win32k Lockdown for the current session is determined once, at startup,
605// and then remains the same for the duration of the session.
606
607static nsIXULRuntime::ContentWin32kLockdownState gWin32kStatus;
608
609// The status of the win32k experiment. It is determined once, at startup,
610// and then remains the same for the duration of the session.
611
612static nsIXULRuntime::ExperimentStatus gWin32kExperimentStatus =
613 nsIXULRuntime::eExperimentStatusUnenrolled;
614
615#ifdef XP_WIN
616// The states for win32k lockdown can be generalized to:
617// - User doesn't meet requirements (bad OS, webrender, remotegl) aka
618// PersistentRequirement
619// - User has Safe Mode enabled, Win32k Disabled by Env Var, or E10S disabled
620// by Env Var aka TemporaryRequirement
621// - User has set the win32k pref to something non-default aka NonDefaultPref
622// - User has been enrolled in the experiment and does what it says aka
623// Enrolled
624// - User does the default aka Default
625//
626// We expect the below behvaior. In the code, there may be references to these
627// behaviors (e.g. [A]) but not always.
628//
629// [A] Becoming enrolled in the experiment while NonDefaultPref disqualifies
630// you upon next browser start
631// [B] Becoming enrolled in the experiment while PersistentRequirement
632// disqualifies you upon next browser start
633// [C] Becoming enrolled in the experiment while TemporaryRequirement does not
634// disqualify you
635// [D] Becoming enrolled in the experiment will only take effect after restart
636// [E] While enrolled, becoming PersistentRequirement will not disqualify you
637// until browser restart, but if the state is present at browser start,
638// will disqualify you. Additionally, it will not affect the session value
639// of gWin32kStatus.
640// XXX(bobowen): I hope both webrender and wbgl.out-of-process require a
641// restart to take effect!
642// [F] While enrolled, becoming NonDefaultPref will disqualify you upon next
643// browser start
644// [G] While enrolled, becoming TemporaryRequirement will _not_ disqualify you,
645// but the session status will prevent win32k lockdown from taking effect.
646
647// The win32k pref
648static const char kPrefWin32k[] = "security.sandbox.content.win32k-disable";
649
650// The current enrollment status as controlled by Normandy. This value is only
651// stored in the default preference branch, and is not persisted across
652// sessions by the preference service. It therefore isn't available early
653// enough at startup, and needs to be synced to a preference in the user
654// branch which is persisted across sessions.
655static const char kPrefWin32kExperimentEnrollmentStatus[] =
656 "security.sandbox.content.win32k-experiment.enrollmentStatus";
657
658// The enrollment status to be used at browser startup. This automatically
659// synced from the above enrollmentStatus preference whenever the latter is
660// changed. We reused the Fission experiment enum - it can have any of the
661// values defined in the `nsIXULRuntime_ExperimentStatus` enum _except_ rollout.
662// Meanings are documented in the declaration of
663// `nsIXULRuntime.fissionExperimentStatus`
664static const char kPrefWin32kExperimentStartupEnrollmentStatus[] =
665 "security.sandbox.content.win32k-experiment.startupEnrollmentStatus";
666
667namespace mozilla {
668
669bool Win32kExperimentEnrolled() {
670 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 670); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsParentProcess()" ")"); do { MOZ_CrashSequence
(__null, 670); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
671 return gWin32kExperimentStatus == nsIXULRuntime::eExperimentStatusControl ||
672 gWin32kExperimentStatus == nsIXULRuntime::eExperimentStatusTreatment;
673}
674
675} // namespace mozilla
676
677static bool Win32kRequirementsUnsatisfied(
678 nsIXULRuntime::ContentWin32kLockdownState aStatus) {
679 return aStatus == nsIXULRuntime::ContentWin32kLockdownState::
680 OperatingSystemNotSupported ||
681 aStatus ==
682 nsIXULRuntime::ContentWin32kLockdownState::MissingWebRender ||
683 aStatus ==
684 nsIXULRuntime::ContentWin32kLockdownState::DecodersArentRemote;
685}
686
687static void Win32kExperimentDisqualify() {
688 MOZ_ASSERT(XRE_IsParentProcess())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(XRE_IsParentProcess())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(XRE_IsParentProcess()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("XRE_IsParentProcess()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 688); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "XRE_IsParentProcess()" ")"); do { MOZ_CrashSequence
(__null, 688); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
689 Preferences::SetUint(kPrefWin32kExperimentEnrollmentStatus,
690 nsIXULRuntime::eExperimentStatusDisqualified);
691}
692
693static void OnWin32kEnrollmentStatusChanged(const char* aPref, void* aData) {
694 auto newStatusInt =
695 Preferences::GetUint(kPrefWin32kExperimentEnrollmentStatus,
696 nsIXULRuntime::eExperimentStatusUnenrolled);
697 auto newStatus = newStatusInt < nsIXULRuntime::eExperimentStatusCount
698 ? nsIXULRuntime::ExperimentStatus(newStatusInt)
699 : nsIXULRuntime::eExperimentStatusDisqualified;
700
701 // Set the startup pref for next browser start [D]
702 Preferences::SetUint(kPrefWin32kExperimentStartupEnrollmentStatus, newStatus);
703}
704
705namespace {
706// This observer is notified during `profile-before-change`, and ensures that
707// the experiment enrollment status is synced over before the browser shuts
708// down, even if it was not modified since win32k was initialized.
709class Win32kEnrollmentStatusShutdownObserver final : public nsIObserver {
710 public:
711 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
712
713 NS_IMETHODvirtual nsresult Observe(nsISupports* aSubject, const char* aTopic,
714 const char16_t* aData) override {
715 MOZ_ASSERT(!strcmp("profile-before-change", aTopic))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!strcmp("profile-before-change", aTopic))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(!strcmp("profile-before-change", aTopic)))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!strcmp(\"profile-before-change\", aTopic)"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 715); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "!strcmp(\"profile-before-change\", aTopic)"
")"); do { MOZ_CrashSequence(__null, 715); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
716 OnWin32kEnrollmentStatusChanged(kPrefWin32kExperimentEnrollmentStatus,
717 nullptr);
718 return NS_OK;
719 }
720
721 private:
722 ~Win32kEnrollmentStatusShutdownObserver() = default;
723};
724NS_IMPL_ISUPPORTS(Win32kEnrollmentStatusShutdownObserver, nsIObserver)MozExternalRefCountType Win32kEnrollmentStatusShutdownObserver
::AddRef(void) { static_assert(!std::is_destructible_v<Win32kEnrollmentStatusShutdownObserver
>, "Reference-counted class " "Win32kEnrollmentStatusShutdownObserver"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 724
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("Win32kEnrollmentStatusShutdownObserver" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("Win32kEnrollmentStatusShutdownObserver" != nullptr)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"Win32kEnrollmentStatusShutdownObserver\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"Win32kEnrollmentStatusShutdownObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 724); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("Win32kEnrollmentStatusShutdownObserver" " not thread-safe")
; nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"Win32kEnrollmentStatusShutdownObserver"), (uint32_t)(sizeof(
*this))); return count; } MozExternalRefCountType Win32kEnrollmentStatusShutdownObserver
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 724
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("Win32kEnrollmentStatusShutdownObserver" != nullptr
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!("Win32kEnrollmentStatusShutdownObserver" != nullptr)
)), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"Win32kEnrollmentStatusShutdownObserver\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 724); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"Win32kEnrollmentStatusShutdownObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 724); __attribute__((nomerge)) ::abort(); } while (false); }
} while (false); if (!mRefCnt.isThreadSafe) _mOwningThread.AssertOwnership
("Win32kEnrollmentStatusShutdownObserver" " not thread-safe")
; const char* const nametmp = "Win32kEnrollmentStatusShutdownObserver"
; nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult Win32kEnrollmentStatusShutdownObserver
::QueryInterface(const nsIID& aIID, void** aInstancePtr) {
do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 724); MOZ_PretendNoReturn
(); } } while (0); nsresult rv = NS_ERROR_FAILURE; static_assert
(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"); static
const QITableEntry table[] = { {&mozilla::detail::kImplementedIID
<Win32kEnrollmentStatusShutdownObserver, nsIObserver>, int32_t
( reinterpret_cast<char*>(static_cast<nsIObserver*>
((Win32kEnrollmentStatusShutdownObserver*)0x1000)) - reinterpret_cast
<char*>((Win32kEnrollmentStatusShutdownObserver*)0x1000
))}, {&mozilla::detail::kImplementedIID<Win32kEnrollmentStatusShutdownObserver
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIObserver*>((Win32kEnrollmentStatusShutdownObserver
*)0x1000))) - reinterpret_cast<char*>((Win32kEnrollmentStatusShutdownObserver
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
725} // namespace
726
727static void OnWin32kChanged(const char* aPref, void* aData) {
728 // If we're actively enrolled in the Win32k experiment, disqualify the user
729 // from the experiment if the Win32k pref is modified. [F]
730 if (Win32kExperimentEnrolled() && Preferences::HasUserValue(kPrefWin32k)) {
731 Win32kExperimentDisqualify();
732 }
733}
734
735#endif // XP_WIN
736
737namespace mozilla {
738void EnsureWin32kInitialized();
739}
740
741nsIXULRuntime::ContentWin32kLockdownState GetLiveWin32kLockdownState() {
742#ifdef XP_WIN
743
744 // HasUserValue The Pref functions can only be called on main thread
745 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 745); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "NS_IsMainThread()" ")"); do { MOZ_CrashSequence
(__null, 745); __attribute__((nomerge)) ::abort(); } while (false
); } } while (false)
;
746
747# ifdef MOZ_BACKGROUNDTASKS1
748 if (BackgroundTasks::IsBackgroundTaskMode()) {
749 // Let's bail out before loading all the graphics libs.
750 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByDefault;
751 }
752# endif
753
754 mozilla::EnsureWin32kInitialized();
755 gfxPlatform::GetPlatform();
756
757 if (EnvHasValue("MOZ_ENABLE_WIN32K")) {
758 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByEnvVar;
759 }
760
761 if (!mozilla::BrowserTabsRemoteAutostart()) {
762 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByE10S;
763 }
764
765 // Win32k lockdown is available on Win8+, but we are initially limiting it to
766 // Windows 10 v1709 (build 16299) or later. Before this COM initialization
767 // currently fails if user32.dll has loaded before it is called.
768 if (!IsWin10FallCreatorsUpdateOrLater()) {
769 return nsIXULRuntime::ContentWin32kLockdownState::
770 OperatingSystemNotSupported;
771 }
772
773 // Some (not sure exactly which) decoders are not compatible
774 if (!PDMFactory::AllDecodersAreRemote()) {
775 return nsIXULRuntime::ContentWin32kLockdownState::DecodersArentRemote;
776 }
777
778 bool prefSetByUser =
779 Preferences::HasUserValue("security.sandbox.content.win32k-disable");
780 bool prefValue = Preferences::GetBool(
781 "security.sandbox.content.win32k-disable", false, PrefValueKind::User);
782 bool defaultValue = Preferences::GetBool(
783 "security.sandbox.content.win32k-disable", false, PrefValueKind::Default);
784
785 if (prefSetByUser) {
786 if (prefValue) {
787 return nsIXULRuntime::ContentWin32kLockdownState::EnabledByUserPref;
788 } else {
789 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByUserPref;
790 }
791 }
792
793 if (gWin32kExperimentStatus ==
794 nsIXULRuntime::ExperimentStatus::eExperimentStatusControl) {
795 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByControlGroup;
796 } else if (gWin32kExperimentStatus ==
797 nsIXULRuntime::ExperimentStatus::eExperimentStatusTreatment) {
798 return nsIXULRuntime::ContentWin32kLockdownState::EnabledByTreatmentGroup;
799 }
800
801 if (defaultValue) {
802 return nsIXULRuntime::ContentWin32kLockdownState::EnabledByDefault;
803 } else {
804 return nsIXULRuntime::ContentWin32kLockdownState::DisabledByDefault;
805 }
806
807#else
808
809 return nsIXULRuntime::ContentWin32kLockdownState::OperatingSystemNotSupported;
810
811#endif
812}
813
814namespace mozilla {
815
816void EnsureWin32kInitialized() {
817 if (gWin32kInitialized) {
818 return;
819 }
820 gWin32kInitialized = true;
821
822#ifdef XP_WIN
823
824 // Initialize the Win32k experiment, configuring win32k's
825 // default, before checking other overrides. This allows opting-out of a
826 // Win32k experiment through about:preferences or about:config from a
827 // safemode session.
828 uint32_t experimentRaw =
829 Preferences::GetUint(kPrefWin32kExperimentStartupEnrollmentStatus,
830 nsIXULRuntime::eExperimentStatusUnenrolled);
831 gWin32kExperimentStatus =
832 experimentRaw < nsIXULRuntime::eExperimentStatusCount
833 ? nsIXULRuntime::ExperimentStatus(experimentRaw)
834 : nsIXULRuntime::eExperimentStatusDisqualified;
835
836 // Watch the experiment enrollment status pref to detect experiment
837 // disqualification, and ensure it is propagated for the next restart.
838 Preferences::RegisterCallback(&OnWin32kEnrollmentStatusChanged,
839 kPrefWin32kExperimentEnrollmentStatus);
840 if (nsCOMPtr<nsIObserverService> observerService =
841 mozilla::services::GetObserverService()) {
842 nsCOMPtr<nsIObserver> shutdownObserver =
843 new Win32kEnrollmentStatusShutdownObserver();
844 observerService->AddObserver(shutdownObserver, "profile-before-change",
845 false);
846 }
847
848 // If the user no longer qualifies because they edited a required pref, check
849 // that. [B] [E]
850 auto tmpStatus = GetLiveWin32kLockdownState();
851 if (Win32kExperimentEnrolled() && Win32kRequirementsUnsatisfied(tmpStatus)) {
852 Win32kExperimentDisqualify();
853 gWin32kExperimentStatus = nsIXULRuntime::eExperimentStatusDisqualified;
854 }
855
856 // If the user has overridden an active experiment by setting a user value for
857 // "security.sandbox.content.win32k-disable", disqualify the user from the
858 // experiment. [A] [F]
859 if (Preferences::HasUserValue(kPrefWin32k) && Win32kExperimentEnrolled()) {
860 Win32kExperimentDisqualify();
861 gWin32kExperimentStatus = nsIXULRuntime::eExperimentStatusDisqualified;
862 }
863
864 // Unlike Fission, we do not configure the default branch based on experiment
865 // enrollment status. Instead we check the startupEnrollmentPref in
866 // GetContentWin32kLockdownState()
867
868 Preferences::RegisterCallback(&OnWin32kChanged, kPrefWin32k);
869
870 // Set the state
871 gWin32kStatus = GetLiveWin32kLockdownState();
872
873#else
874 gWin32kStatus =
875 nsIXULRuntime::ContentWin32kLockdownState::OperatingSystemNotSupported;
876 gWin32kExperimentStatus = nsIXULRuntime::eExperimentStatusUnenrolled;
877
878#endif // XP_WIN
879}
880
881nsIXULRuntime::ContentWin32kLockdownState GetWin32kLockdownState() {
882#ifdef XP_WIN
883
884 mozilla::EnsureWin32kInitialized();
885 return gWin32kStatus;
886
887#else
888
889 return nsIXULRuntime::ContentWin32kLockdownState::OperatingSystemNotSupported;
890
891#endif
892}
893
894} // namespace mozilla
895
896// End Win32k Infrastructure ==========================================
897
898// Fission Infrastructure =============================================
899
900// Fission enablement for the current session is determined once, at startup,
901// and then remains the same for the duration of the session.
902//
903// The following factors determine whether or not Fission is enabled for a
904// session, in order of precedence:
905//
906// - Safe mode: In safe mode, Fission is never enabled.
907//
908// - The MOZ_FORCE_ENABLE_FISSION environment variable: If set to any value,
909// Fission will be enabled.
910//
911// - The 'fission.autostart' preference, if it has been configured by the user.
912static const char kPrefFissionAutostart[] = "fission.autostart";
913
914// The computed FissionAutostart value for the session, read by content
915// processes to initialize gFissionAutostart.
916//
917// This pref is locked, and only configured on the default branch, so should
918// never be persisted in a profile.
919static const char kPrefFissionAutostartSession[] = "fission.autostart.session";
920
921//
922// The computed FissionAutostart value for the session, read by content
923// processes to initialize gFissionAutostart.
924
925static bool gFissionAutostart = false;
926static bool gFissionAutostartInitialized = false;
927static nsIXULRuntime::FissionDecisionStatus gFissionDecisionStatus;
928static void EnsureFissionAutostartInitialized() {
929 if (gFissionAutostartInitialized) {
930 return;
931 }
932 gFissionAutostartInitialized = true;
933
934 if (!XRE_IsParentProcess()) {
935 // This pref is configured for the current session by the parent process.
936 gFissionAutostart = Preferences::GetBool(kPrefFissionAutostartSession,
937 false, PrefValueKind::Default);
938 return;
939 }
940
941 if (!BrowserTabsRemoteAutostart()) {
942 gFissionAutostart = false;
943 if (gBrowserTabsRemoteStatus == kE10sForceDisabled) {
944 gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledByE10sEnv;
945 } else {
946 gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledByE10sOther;
947 }
948 } else if (EnvHasValue("MOZ_FORCE_ENABLE_FISSION")) {
949 gFissionAutostart = true;
950 gFissionDecisionStatus = nsIXULRuntime::eFissionEnabledByEnv;
951 } else if (EnvHasValue("MOZ_FORCE_DISABLE_FISSION")) {
952 gFissionAutostart = false;
953 gFissionDecisionStatus = nsIXULRuntime::eFissionDisabledByEnv;
954 } else {
955 // NOTE: This will take into account changes to the default due to
956 // `InitializeFissionExperimentStatus`.
957 gFissionAutostart = Preferences::GetBool(kPrefFissionAutostart, false);
958 if (Preferences::HasUserValue(kPrefFissionAutostart)) {
959 gFissionDecisionStatus = gFissionAutostart
960 ? nsIXULRuntime::eFissionEnabledByUserPref
961 : nsIXULRuntime::eFissionDisabledByUserPref;
962 } else {
963 gFissionDecisionStatus = gFissionAutostart
964 ? nsIXULRuntime::eFissionEnabledByDefault
965 : nsIXULRuntime::eFissionDisabledByDefault;
966 }
967 }
968
969 // Content processes cannot run the same logic as we're running in the parent
970 // process, as the current value of various preferences may have changed
971 // between launches. Instead, the content process will read the default branch
972 // of the locked `fission.autostart.session` preference to determine the value
973 // determined by this method.
974 Preferences::Unlock(kPrefFissionAutostartSession);
975 Preferences::ClearUser(kPrefFissionAutostartSession);
976 Preferences::SetBool(kPrefFissionAutostartSession, gFissionAutostart,
977 PrefValueKind::Default);
978 Preferences::Lock(kPrefFissionAutostartSession);
979}
980
981namespace mozilla {
982
983bool FissionAutostart() {
984 EnsureFissionAutostartInitialized();
985 return gFissionAutostart;
986}
987
988} // namespace mozilla
989
990// End Fission Infrastructure =========================================
991
992namespace mozilla {
993
994bool SessionStorePlatformCollection() {
995 return !StaticPrefs::
996 browser_sessionstore_disable_platform_collection_AtStartup_DoNotUseDirectly();
997}
998
999bool BFCacheInParent() {
1000 return StaticPrefs::fission_bfcacheInParent_DoNotUseDirectly();
1001}
1002
1003} // namespace mozilla
1004
1005/**
1006 * The nsXULAppInfo object implements nsIFactory so that it can be its own
1007 * singleton.
1008 */
1009class nsXULAppInfo : public nsIXULAppInfo,
1010#ifdef XP_WIN
1011 public nsIWinAppHelper,
1012#endif
1013 public nsICrashReporter,
1014 public nsIFinishDumpingCallback,
1015 public nsIXULRuntime
1016
1017{
1018 public:
1019 constexpr nsXULAppInfo() = default;
1020 NS_DECL_ISUPPORTS_INHERITEDpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override;
1021 NS_DECL_NSIPLATFORMINFOvirtual nsresult GetPlatformVersion(nsACString& aPlatformVersion
) override; virtual nsresult GetPlatformBuildID(nsACString&
aPlatformBuildID) override;
1022 NS_DECL_NSIXULAPPINFOvirtual nsresult GetVendor(nsACString& aVendor) override;
virtual nsresult GetName(nsACString& aName) override; virtual
nsresult GetID(nsACString& aID) override; virtual nsresult
GetVersion(nsACString& aVersion) override; virtual nsresult
GetAppBuildID(nsACString& aAppBuildID) override; virtual
nsresult GetUAName(nsACString& aUAName) override; virtual
nsresult GetSourceURL(nsACString& aSourceURL) override; virtual
nsresult GetUpdateURL(nsACString& aUpdateURL) override; virtual
nsresult GetRemotingName(nsACString& aRemotingName) override
;
1023 NS_DECL_NSIXULRUNTIMEvirtual nsresult GetInSafeMode(bool *aInSafeMode) override; virtual
nsresult GetWin32kExperimentStatus(nsIXULRuntime::ExperimentStatus
*aWin32kExperimentStatus) override; virtual nsresult GetWin32kLiveStatusTestingOnly
(nsIXULRuntime::ContentWin32kLockdownState *aWin32kLiveStatusTestingOnly
) override; virtual nsresult GetWin32kSessionStatus(nsIXULRuntime
::ContentWin32kLockdownState *aWin32kSessionStatus) override;
virtual nsresult GetFissionAutostart(bool *aFissionAutostart
) override; virtual nsresult GetFissionDecisionStatus(nsIXULRuntime
::FissionDecisionStatus *aFissionDecisionStatus) override; virtual
nsresult GetFissionDecisionStatusString(nsACString& aFissionDecisionStatusString
) override; virtual nsresult GetSessionStorePlatformCollection
(bool *aSessionStorePlatformCollection) override; virtual nsresult
GetLogConsoleErrors(bool *aLogConsoleErrors) override; virtual
nsresult SetLogConsoleErrors(bool aLogConsoleErrors) override
; virtual nsresult GetOS(nsACString& aOS) override; virtual
nsresult GetXPCOMABI(nsACString& aXPCOMABI) override; virtual
nsresult GetWidgetToolkit(nsACString& aWidgetToolkit) override
; virtual nsresult GetProcessType(uint32_t *aProcessType) override
; virtual nsresult GetProcessID(uint32_t *aProcessID) override
; virtual nsresult GetUniqueProcessID(uint64_t *aUniqueProcessID
) override; virtual nsresult GetRemoteType(nsACString& aRemoteType
) override; virtual nsresult GetBrowserTabsRemoteAutostart(bool
*aBrowserTabsRemoteAutostart) override; virtual nsresult GetMaxWebProcessCount
(uint32_t *aMaxWebProcessCount) override; virtual nsresult GetAccessibilityEnabled
(bool *aAccessibilityEnabled) override; virtual nsresult GetAccessibilityInstantiator
(nsAString& aAccessibilityInstantiator) override; virtual
nsresult GetIs64Bit(bool *aIs64Bit) override; virtual nsresult
GetIsTextRecognitionSupported(bool *aIsTextRecognitionSupported
) override; virtual nsresult InvalidateCachesOnRestart(void) override
; virtual nsresult MarkProfileEncryptedDatabases(void) override
; virtual nsresult GetReplacedLockTime(PRTime *aReplacedLockTime
) override; virtual nsresult GetDefaultUpdateChannel(nsACString
& aDefaultUpdateChannel) override; virtual nsresult GetDistributionID
(nsACString& aDistributionID) override; virtual nsresult GetWindowsDLLBlocklistStatus
(bool *aWindowsDLLBlocklistStatus) override; virtual nsresult
GetRestartedByOS(bool *aRestartedByOS) override; virtual nsresult
GetNativeMenubar(bool *aNativeMenubar) override; virtual nsresult
GetChromeColorSchemeIsDark(bool *aChromeColorSchemeIsDark) override
; virtual nsresult GetContentThemeDerivedColorSchemeIsDark(bool
*aContentThemeDerivedColorSchemeIsDark) override; virtual nsresult
GetPrefersReducedMotion(bool *aPrefersReducedMotion) override
; virtual nsresult GetDrawInTitlebar(bool *aDrawInTitlebar) override
; virtual nsresult GetCaretBlinkCount(int32_t *aCaretBlinkCount
) override; virtual nsresult GetCaretBlinkTime(int32_t *aCaretBlinkTime
) override; virtual nsresult GetDesktopEnvironment(nsACString
& aDesktopEnvironment) override; virtual nsresult GetIsWayland
(bool *aIsWayland) override; virtual nsresult GetProcessStartupShortcut
(nsAString& aProcessStartupShortcut) override; virtual nsresult
GetLauncherProcessState(uint32_t *aLauncherProcessState) override
; virtual nsresult GetLastAppVersion(nsACString& aLastAppVersion
) override; virtual nsresult GetLastAppBuildID(nsACString&
aLastAppBuildID) override;
1024 NS_DECL_NSICRASHREPORTERvirtual nsresult GetCrashReporterEnabled(bool *aCrashReporterEnabled
) override; virtual nsresult SetEnabled(bool enabled) override
; virtual nsresult GetServerURL(nsIURL **aServerURL) override
; virtual nsresult SetServerURL(nsIURL *aServerURL) override;
virtual nsresult GetMinidumpPath(nsIFile **aMinidumpPath) override
; virtual nsresult SetMinidumpPath(nsIFile *aMinidumpPath) override
; virtual nsresult GetMinidumpForID(const nsAString& id, nsIFile
**_retval) override; virtual nsresult GetExtraFileForID(const
nsAString& id, nsIFile **_retval) override; virtual nsresult
AnnotateCrashReport(const nsACString& key, JS::Handle<
JS::Value> data, JSContext* cx) override; virtual nsresult
RemoveCrashReportAnnotation(const nsACString& key) override
; virtual nsresult IsAnnotationValid(const nsACString& value
, bool *_retval) override; virtual nsresult IsAnnotationAllowedForReport
(const nsACString& value, bool *_retval) override; virtual
nsresult AppendAppNotesToCrashReport(const nsACString& data
) override; virtual nsresult WriteMinidumpForException(void *
aExceptionInfo) override; virtual nsresult AppendObjCExceptionInfoToAppNotes
(void * aException) override; virtual nsresult GetSubmitReports
(bool *aSubmitReports) override; virtual nsresult SetSubmitReports
(bool aSubmitReports) override; virtual nsresult UpdateCrashEventsDir
(void) override; virtual nsresult SaveMemoryReport(void) override
;
1025 NS_DECL_NSIFINISHDUMPINGCALLBACKvirtual nsresult Callback(nsISupports *data) override;
1026#ifdef XP_WIN
1027 NS_DECL_NSIWINAPPHELPER
1028#endif
1029};
1030
1031NS_INTERFACE_MAP_BEGIN(nsXULAppInfo)nsresult nsXULAppInfo::QueryInterface(const nsIID& aIID, void
** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(
NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1031); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
1032 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXULRuntime)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<nsIXULRuntime*>(this))
; else
1033 NS_INTERFACE_MAP_ENTRY(nsIXULRuntime)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIXULRuntime>)) foundInterface =
static_cast<nsIXULRuntime*>(this); else
1034#ifdef XP_WIN
1035 NS_INTERFACE_MAP_ENTRY(nsIWinAppHelper)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIWinAppHelper>)) foundInterface
= static_cast<nsIWinAppHelper*>(this); else
1036#endif
1037 NS_INTERFACE_MAP_ENTRY(nsICrashReporter)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsICrashReporter>)) foundInterface
= static_cast<nsICrashReporter*>(this); else
1038 NS_INTERFACE_MAP_ENTRY(nsIFinishDumpingCallback)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIFinishDumpingCallback>)) foundInterface
= static_cast<nsIFinishDumpingCallback*>(this); else
1039 NS_INTERFACE_MAP_ENTRY(nsIPlatformInfo)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIPlatformInfo>)) foundInterface
= static_cast<nsIPlatformInfo*>(this); else
1040 NS_INTERFACE_MAP_ENTRY_CONDITIONAL(nsIXULAppInfo,if ((gAppData || XRE_IsContentProcess()) && aIID.Equals
(mozilla::detail::kImplementedIID<std::remove_reference_t<
decltype(*this)>, nsIXULAppInfo>)) foundInterface = static_cast
<nsIXULAppInfo*>(this); else
1041 gAppData || XRE_IsContentProcess())if ((gAppData || XRE_IsContentProcess()) && aIID.Equals
(mozilla::detail::kImplementedIID<std::remove_reference_t<
decltype(*this)>, nsIXULAppInfo>)) foundInterface = static_cast
<nsIXULAppInfo*>(this); else
1042NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::kIID
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aIID.Equals((nsISupports::kIID))", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1042); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::kIID))"
")"); do { MOZ_CrashSequence(__null, 1042); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
1043
1044NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType
1045nsXULAppInfo::AddRef() { return 1; }
1046
1047NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType
1048nsXULAppInfo::Release() { return 1; }
1049
1050NS_IMETHODIMPnsresult
1051nsXULAppInfo::GetVendor(nsACString& aResult) {
1052 if (XRE_IsContentProcess()) {
1053 ContentChild* cc = ContentChild::GetSingleton();
1054 aResult = cc->GetAppInfo().vendor;
1055 return NS_OK;
1056 }
1057 aResult.Assign(gAppData->vendor);
1058
1059 return NS_OK;
1060}
1061
1062NS_IMETHODIMPnsresult
1063nsXULAppInfo::GetName(nsACString& aResult) {
1064 if (XRE_IsContentProcess()) {
1065 ContentChild* cc = ContentChild::GetSingleton();
1066 aResult = cc->GetAppInfo().name;
1067 return NS_OK;
1068 }
1069
1070#ifdef MOZ_WIDGET_ANDROID
1071 nsCString name = java::GeckoAppShell::GetAppName()->ToCString();
1072 aResult.Assign(std::move(name));
1073#else
1074 aResult.Assign(gAppData->name);
1075#endif
1076
1077 return NS_OK;
1078}
1079
1080NS_IMETHODIMPnsresult
1081nsXULAppInfo::GetID(nsACString& aResult) {
1082 if (XRE_IsContentProcess()) {
1083 ContentChild* cc = ContentChild::GetSingleton();
1084 aResult = cc->GetAppInfo().ID;
1085 return NS_OK;
1086 }
1087 aResult.Assign(gAppData->ID);
1088
1089 return NS_OK;
1090}
1091
1092NS_IMETHODIMPnsresult
1093nsXULAppInfo::GetVersion(nsACString& aResult) {
1094 if (XRE_IsContentProcess()) {
1095 ContentChild* cc = ContentChild::GetSingleton();
1096 aResult = cc->GetAppInfo().version;
1097 return NS_OK;
1098 }
1099 aResult.Assign(gAppData->version);
1100
1101 return NS_OK;
1102}
1103
1104NS_IMETHODIMPnsresult
1105nsXULAppInfo::GetPlatformVersion(nsACString& aResult) {
1106 aResult.Assign(gToolkitVersion);
1107
1108 return NS_OK;
1109}
1110
1111NS_IMETHODIMPnsresult
1112nsXULAppInfo::GetAppBuildID(nsACString& aResult) {
1113 if (XRE_IsContentProcess()) {
1114 ContentChild* cc = ContentChild::GetSingleton();
1115 aResult = cc->GetAppInfo().buildID;
1116 return NS_OK;
1117 }
1118 aResult.Assign(gAppData->buildID);
1119
1120 return NS_OK;
1121}
1122
1123NS_IMETHODIMPnsresult
1124nsXULAppInfo::GetPlatformBuildID(nsACString& aResult) {
1125 aResult.Assign(gToolkitBuildID);
1126
1127 return NS_OK;
1128}
1129
1130NS_IMETHODIMPnsresult
1131nsXULAppInfo::GetUAName(nsACString& aResult) {
1132 if (XRE_IsContentProcess()) {
1133 ContentChild* cc = ContentChild::GetSingleton();
1134 aResult = cc->GetAppInfo().UAName;
1135 return NS_OK;
1136 }
1137 aResult.Assign(gAppData->UAName);
1138
1139 return NS_OK;
1140}
1141
1142NS_IMETHODIMPnsresult
1143nsXULAppInfo::GetSourceURL(nsACString& aResult) {
1144 if (XRE_IsContentProcess()) {
1145 ContentChild* cc = ContentChild::GetSingleton();
1146 aResult = cc->GetAppInfo().sourceURL;
1147 return NS_OK;
1148 }
1149 aResult.Assign(gAppData->sourceURL);
1150
1151 return NS_OK;
1152}
1153
1154NS_IMETHODIMPnsresult
1155nsXULAppInfo::GetUpdateURL(nsACString& aResult) {
1156 if (XRE_IsContentProcess()) {
1157 ContentChild* cc = ContentChild::GetSingleton();
1158 aResult = cc->GetAppInfo().updateURL;
1159 return NS_OK;
1160 }
1161 aResult.Assign(gAppData->updateURL);
1162
1163 return NS_OK;
1164}
1165
1166NS_IMETHODIMPnsresult
1167nsXULAppInfo::GetRemotingName(nsACString& aResult) {
1168 if (XRE_IsContentProcess()) {
1169 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")"); do { MOZ_CrashSequence(__null, 1171)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1170 "nsXULAppInfo::remotingName should not be accessed from the "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")"); do { MOZ_CrashSequence(__null, 1171)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
1171 "content process")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1171); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"nsXULAppInfo::remotingName should not be accessed from the "
"content process" ")"); do { MOZ_CrashSequence(__null, 1171)
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
1172 return NS_ERROR_UNEXPECTED;
1173 }
1174 aResult.Assign(gAppData->remotingName);
1175
1176 return NS_OK;
1177}
1178
1179NS_IMETHODIMPnsresult
1180nsXULAppInfo::GetLogConsoleErrors(bool* aResult) {
1181 *aResult = gLogConsoleErrors;
1182 return NS_OK;
1183}
1184
1185NS_IMETHODIMPnsresult
1186nsXULAppInfo::SetLogConsoleErrors(bool aValue) {
1187 gLogConsoleErrors = aValue;
1188 return NS_OK;
1189}
1190
1191NS_IMETHODIMPnsresult
1192nsXULAppInfo::GetInSafeMode(bool* aResult) {
1193 *aResult = gSafeMode;
1194 return NS_OK;
1195}
1196
1197NS_IMETHODIMPnsresult
1198nsXULAppInfo::GetOS(nsACString& aResult) {
1199 aResult.AssignLiteral(OS_TARGET"Linux");
1200 return NS_OK;
1201}
1202
1203NS_IMETHODIMPnsresult
1204nsXULAppInfo::GetXPCOMABI(nsACString& aResult) {
1205#ifdef TARGET_XPCOM_ABI"x86_64-gcc3"
1206 aResult.AssignLiteral(TARGET_XPCOM_ABI"x86_64-gcc3");
1207 return NS_OK;
1208#else
1209 return NS_ERROR_NOT_AVAILABLE;
1210#endif
1211}
1212
1213NS_IMETHODIMPnsresult
1214nsXULAppInfo::GetWidgetToolkit(nsACString& aResult) {
1215 aResult.AssignLiteral(MOZ_WIDGET_TOOLKIT"gtk");
1216 return NS_OK;
1217}
1218
1219// Ensure that the GeckoProcessType enum, defined in xpcom/build/nsXULAppAPI.h,
1220// is synchronized with the const unsigned longs defined in
1221// xpcom/system/nsIXULRuntime.idl.
1222#define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
1223 process_bin_type, procinfo_typename, \
1224 webidl_typename, allcaps_name) \
1225 static_assert(nsIXULRuntime::PROCESS_TYPE_##allcaps_name == \
1226 static_cast<int>(GeckoProcessType_##enum_name), \
1227 "GeckoProcessType in nsXULAppAPI.h not synchronized with " \
1228 "nsIXULRuntime.idl");
1229#include "mozilla/GeckoProcessTypes.inc"
1230#undef GECKO_PROCESS_TYPE
1231
1232// .. and ensure that that is all of them:
1233static_assert(GeckoProcessType_Utility + 1 == GeckoProcessType_End,
1234 "Did not find the final GeckoProcessType");
1235
1236NS_IMETHODIMPnsresult
1237nsXULAppInfo::GetProcessType(uint32_t* aResult) {
1238 NS_ENSURE_ARG_POINTER(aResult)do { if ((__builtin_expect(!!(!(aResult)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aResult" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1238); return
NS_ERROR_INVALID_POINTER; } } while (false)
;
1239 *aResult = XRE_GetProcessType();
1240 return NS_OK;
1241}
1242
1243NS_IMETHODIMPnsresult
1244nsXULAppInfo::GetProcessID(uint32_t* aResult) {
1245#ifdef XP_WIN
1246 *aResult = GetCurrentProcessId();
1247#else
1248 *aResult = getpid();
1249#endif
1250 return NS_OK;
1251}
1252
1253NS_IMETHODIMPnsresult
1254nsXULAppInfo::GetUniqueProcessID(uint64_t* aResult) {
1255 if (XRE_IsContentProcess()) {
1256 ContentChild* cc = ContentChild::GetSingleton();
1257 *aResult = cc->GetID();
1258 } else {
1259 *aResult = 0;
1260 }
1261 return NS_OK;
1262}
1263
1264NS_IMETHODIMPnsresult
1265nsXULAppInfo::GetRemoteType(nsACString& aRemoteType) {
1266 if (XRE_IsContentProcess()) {
1267 aRemoteType = ContentChild::GetSingleton()->GetRemoteType().Stringify();
1268 } else {
1269 aRemoteType = dom::RemoteType::NotRemote().Stringify();
1270 }
1271
1272 return NS_OK;
1273}
1274
1275constinit static nsCString gLastAppVersion;
1276constinit static nsCString gLastAppBuildID;
1277
1278// Whether the loaded profile's compatibility.ini carries EncryptedDatabases=1.
1279// Populated by CheckCompatibility() (which already parses compatibility.ini)
1280// and consulted by the encryption-compatibility gate in XRE_mainStartup.
1281static bool gProfileEncryptedDatabases = false;
1282
1283NS_IMETHODIMPnsresult
1284nsXULAppInfo::GetLastAppVersion(nsACString& aResult) {
1285 if (XRE_IsContentProcess()) {
1286 return NS_ERROR_NOT_AVAILABLE;
1287 }
1288
1289 if (!gLastAppVersion.IsVoid() && gLastAppVersion.IsEmpty()) {
1290 NS_WARNING("Attempt to retrieve lastAppVersion before it has been set.")NS_DebugBreak(NS_DEBUG_WARNING, "Attempt to retrieve lastAppVersion before it has been set."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
1290)
;
1291 return NS_ERROR_NOT_AVAILABLE;
1292 }
1293
1294 aResult.Assign(gLastAppVersion);
1295 return NS_OK;
1296}
1297
1298NS_IMETHODIMPnsresult
1299nsXULAppInfo::GetLastAppBuildID(nsACString& aResult) {
1300 if (XRE_IsContentProcess()) {
1301 return NS_ERROR_NOT_AVAILABLE;
1302 }
1303
1304 if (!gLastAppBuildID.IsVoid() && gLastAppBuildID.IsEmpty()) {
1305 NS_WARNING("Attempt to retrieve lastAppBuildID before it has been set.")NS_DebugBreak(NS_DEBUG_WARNING, "Attempt to retrieve lastAppBuildID before it has been set."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
1305)
;
1306 return NS_ERROR_NOT_AVAILABLE;
1307 }
1308
1309 aResult.Assign(gLastAppBuildID);
1310 return NS_OK;
1311}
1312
1313NS_IMETHODIMPnsresult
1314nsXULAppInfo::GetFissionAutostart(bool* aResult) {
1315 *aResult = FissionAutostart();
1316 return NS_OK;
1317}
1318
1319NS_IMETHODIMPnsresult
1320nsXULAppInfo::GetWin32kExperimentStatus(ExperimentStatus* aResult) {
1321 if (!XRE_IsParentProcess()) {
1322 return NS_ERROR_NOT_AVAILABLE;
1323 }
1324
1325 EnsureWin32kInitialized();
1326 *aResult = gWin32kExperimentStatus;
1327 return NS_OK;
1328}
1329
1330NS_IMETHODIMPnsresult
1331nsXULAppInfo::GetWin32kLiveStatusTestingOnly(
1332 nsIXULRuntime::ContentWin32kLockdownState* aResult) {
1333 if (!XRE_IsParentProcess()) {
1334 return NS_ERROR_NOT_AVAILABLE;
1335 }
1336
1337 EnsureWin32kInitialized();
1338 *aResult = GetLiveWin32kLockdownState();
1339 return NS_OK;
1340}
1341
1342NS_IMETHODIMPnsresult
1343nsXULAppInfo::GetWin32kSessionStatus(
1344 nsIXULRuntime::ContentWin32kLockdownState* aResult) {
1345 if (!XRE_IsParentProcess()) {
1346 return NS_ERROR_NOT_AVAILABLE;
1347 }
1348
1349 EnsureWin32kInitialized();
1350 *aResult = gWin32kStatus;
1351 return NS_OK;
1352}
1353
1354NS_IMETHODIMPnsresult
1355nsXULAppInfo::GetFissionDecisionStatus(FissionDecisionStatus* aResult) {
1356 if (!XRE_IsParentProcess()) {
1357 return NS_ERROR_NOT_AVAILABLE;
1358 }
1359
1360 EnsureFissionAutostartInitialized();
1361
1362 MOZ_ASSERT(gFissionDecisionStatus != eFissionStatusUnknown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gFissionDecisionStatus != eFissionStatusUnknown)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(gFissionDecisionStatus != eFissionStatusUnknown))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("gFissionDecisionStatus != eFissionStatusUnknown"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1362); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "gFissionDecisionStatus != eFissionStatusUnknown"
")"); do { MOZ_CrashSequence(__null, 1362); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1363 *aResult = gFissionDecisionStatus;
1364 return NS_OK;
1365}
1366
1367NS_IMETHODIMPnsresult
1368nsXULAppInfo::GetFissionDecisionStatusString(nsACString& aResult) {
1369 if (!XRE_IsParentProcess()) {
1370 return NS_ERROR_NOT_AVAILABLE;
1371 }
1372
1373 EnsureFissionAutostartInitialized();
1374 switch (gFissionDecisionStatus) {
1375 case eFissionDisabledByE10sEnv:
1376 aResult = "disabledByE10sEnv";
1377 break;
1378 case eFissionEnabledByEnv:
1379 aResult = "enabledByEnv";
1380 break;
1381 case eFissionDisabledByEnv:
1382 aResult = "disabledByEnv";
1383 break;
1384 case eFissionEnabledByDefault:
1385 aResult = "enabledByDefault";
1386 break;
1387 case eFissionDisabledByDefault:
1388 aResult = "disabledByDefault";
1389 break;
1390 case eFissionEnabledByUserPref:
1391 aResult = "enabledByUserPref";
1392 break;
1393 case eFissionDisabledByUserPref:
1394 aResult = "disabledByUserPref";
1395 break;
1396 case eFissionDisabledByE10sOther:
1397 aResult = "disabledByE10sOther";
1398 break;
1399 default:
1400 MOZ_ASSERT_UNREACHABLE("Unexpected enum value")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Unexpected enum value" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1400); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Unexpected enum value" ")"); do {
MOZ_CrashSequence(__null, 1400); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1401 }
1402 return NS_OK;
1403}
1404
1405NS_IMETHODIMPnsresult
1406nsXULAppInfo::GetSessionStorePlatformCollection(bool* aResult) {
1407 *aResult = SessionStorePlatformCollection();
1408 return NS_OK;
1409}
1410
1411NS_IMETHODIMPnsresult
1412nsXULAppInfo::GetBrowserTabsRemoteAutostart(bool* aResult) {
1413 *aResult = BrowserTabsRemoteAutostart();
1414 return NS_OK;
1415}
1416
1417NS_IMETHODIMPnsresult
1418nsXULAppInfo::GetMaxWebProcessCount(uint32_t* aResult) {
1419 *aResult = mozilla::GetMaxWebProcessCount();
1420 return NS_OK;
1421}
1422
1423NS_IMETHODIMPnsresult
1424nsXULAppInfo::GetAccessibilityEnabled(bool* aResult) {
1425#ifdef ACCESSIBILITY1
1426 *aResult = GetAccService() != nullptr;
1427#else
1428 *aResult = false;
1429#endif
1430 return NS_OK;
1431}
1432
1433NS_IMETHODIMPnsresult
1434nsXULAppInfo::GetAccessibilityInstantiator(nsAString& aInstantiator) {
1435 aInstantiator.Truncate();
1436#if defined(ACCESSIBILITY1)
1437 if (GetAccService()) {
1438 a11y::GetHumanReadableInstantiatorStr(aInstantiator);
1439# if defined(XP_WIN)
1440 aInstantiator.AppendLiteral("|");
1441
1442 nsCOMPtr<nsIFile> oopClientExe;
1443 if (a11y::GetInstantiator(getter_AddRefs(oopClientExe))) {
1444 nsAutoString oopClientInfo;
1445 if (NS_SUCCEEDED(oopClientExe->GetPath(oopClientInfo))((bool)(__builtin_expect(!!(!NS_FAILED_impl(oopClientExe->
GetPath(oopClientInfo))), 1)))
) {
1446 aInstantiator.Append(oopClientInfo);
1447 }
1448 }
1449# endif
1450 }
1451#endif
1452 return NS_OK;
1453}
1454
1455NS_IMETHODIMPnsresult
1456nsXULAppInfo::GetIs64Bit(bool* aResult) {
1457#ifdef HAVE_64BIT_BUILD1
1458 *aResult = true;
1459#else
1460 *aResult = false;
1461#endif
1462 return NS_OK;
1463}
1464
1465NS_IMETHODIMPnsresult
1466nsXULAppInfo::GetIsTextRecognitionSupported(bool* aResult) {
1467 *aResult = widget::TextRecognition::IsSupported();
1468 return NS_OK;
1469}
1470
1471NS_IMETHODIMPnsresult
1472nsXULAppInfo::InvalidateCachesOnRestart() {
1473 nsCOMPtr<nsIFile> file;
1474 nsresult rv =
1475 NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP"ProfDS", getter_AddRefs(file));
1476 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
1477 if (!file) return NS_ERROR_NOT_AVAILABLE;
1478
1479 file->AppendNative(FILE_COMPATIBILITY_INFO"compatibility.ini"_ns);
1480
1481 nsINIParsernsINIParser_internal parser;
1482 rv = parser.Init(file);
1483 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1484 // This fails if compatibility.ini is not there, so we'll
1485 // flush the caches on the next restart anyways.
1486 return NS_OK;
1487 }
1488
1489 nsAutoCString buf;
1490 rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
1491
1492 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1493 PRFileDesc* fd;
1494 rv = file->OpenNSPRFileDesc(PR_RDWR0x04 | PR_APPEND0x10, 0600, &fd);
1495 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1496 NS_ERROR("could not create output stream")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "could not create output stream"
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
1496); MOZ_PretendNoReturn(); } while (0)
;
1497 return NS_ERROR_NOT_AVAILABLE;
1498 }
1499 static const char kInvalidationHeader[] =
1500 NS_LINEBREAK"\012" "InvalidateCaches=1" NS_LINEBREAK"\012";
1501 PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
1502 PR_Close(fd);
1503 }
1504 return NS_OK;
1505}
1506
1507nsresult mozilla::MarkProfileEncryptedDatabases() {
1508 // Append the EncryptedDatabases marker to compatibility.ini (modeled on
1509 // InvalidateCachesOnRestart above). Read back by CheckCompatibility() on the
1510 // next startup so the encryption gate can refuse to launch a build whose
1511 // pref disagrees with the now-encrypted profile. Append-only: the marker is
1512 // never removed (a profile that has held encrypted databases stays marked).
1513 nsCOMPtr<nsIFile> file;
1514 nsresult rv =
1515 NS_GetSpecialDirectory(NS_APP_PROFILE_DIR_STARTUP"ProfDS", getter_AddRefs(file));
1516 // No resolvable startup profile directory (xpcshell, or a background task /
1517 // very early startup with no profile yet): there is no persistent
1518 // compatibility.ini to gate a future launch, so there is nothing to mark and
1519 // nothing to protect. Treat this as a benign no-op. Returning a failure here
1520 // would flip sMarkerWriteFailed (see MarkProfileEncryptedIfNeeded) and refuse
1521 // every DEK mint for the session, breaking all in-profile opens under
1522 // xpcshell with the pref on. A genuine write failure on an existing profile
1523 // is still surfaced below.
1524 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !file) return NS_OK;
1525
1526 file->AppendNative(FILE_COMPATIBILITY_INFO"compatibility.ini"_ns);
1527
1528 nsINIParsernsINIParser_internal parser;
1529 rv = parser.Init(file);
1530 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1531 // No compatibility.ini yet (WriteVersion creates it once per profile);
1532 // the marker will be written on a later startup.
1533 return NS_OK;
1534 }
1535
1536 nsAutoCString buf;
1537 rv = parser.GetString("Compatibility", "EncryptedDatabases", buf);
1538 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
1539 // Already marked.
1540 return NS_OK;
1541 }
1542
1543 PRFileDesc* fd;
1544 rv = file->OpenNSPRFileDesc(PR_RDWR0x04 | PR_APPEND0x10, 0600, &fd);
1545 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1546 return NS_ERROR_NOT_AVAILABLE;
1547 }
1548 static const char kEncryptedHeader[] =
1549 NS_LINEBREAK"\012" "EncryptedDatabases=1" NS_LINEBREAK"\012";
1550 PR_Write(fd, kEncryptedHeader, sizeof(kEncryptedHeader) - 1);
1551 PR_Close(fd);
1552 return NS_OK;
1553}
1554
1555NS_IMETHODIMPnsresult
1556nsXULAppInfo::MarkProfileEncryptedDatabases() {
1557 return mozilla::MarkProfileEncryptedDatabases();
1558}
1559
1560NS_IMETHODIMPnsresult
1561nsXULAppInfo::GetReplacedLockTime(PRTime* aReplacedLockTime) {
1562 if (!gProfileLock) return NS_ERROR_NOT_AVAILABLE;
1563 gProfileLock->GetReplacedLockTime(aReplacedLockTime);
1564 return NS_OK;
1565}
1566
1567NS_IMETHODIMPnsresult
1568nsXULAppInfo::GetDefaultUpdateChannel(nsACString& aResult) {
1569 aResult.AssignLiteral(MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL)"default");
1570 return NS_OK;
1571}
1572
1573NS_IMETHODIMPnsresult
1574nsXULAppInfo::GetDistributionID(nsACString& aResult) {
1575 aResult.AssignLiteral(MOZ_DISTRIBUTION_ID"org.mozilla");
1576 return NS_OK;
1577}
1578
1579NS_IMETHODIMPnsresult
1580nsXULAppInfo::GetWindowsDLLBlocklistStatus(bool* aResult) {
1581#if defined(HAS_DLL_BLOCKLIST)
1582 *aResult = DllBlocklist_CheckStatus();
1583#else
1584 *aResult = false;
1585#endif
1586 return NS_OK;
1587}
1588
1589NS_IMETHODIMPnsresult
1590nsXULAppInfo::GetRestartedByOS(bool* aResult) {
1591 *aResult = gRestartedByOS;
1592 return NS_OK;
1593}
1594
1595NS_IMETHODIMPnsresult
1596nsXULAppInfo::GetChromeColorSchemeIsDark(bool* aResult) {
1597 *aResult = PreferenceSheet::ColorSchemeForChrome() == ColorScheme::Dark;
1598 return NS_OK;
1599}
1600
1601NS_IMETHODIMPnsresult
1602nsXULAppInfo::GetNativeMenubar(bool* aResult) {
1603 *aResult = !!LookAndFeel::GetInt(LookAndFeel::IntID::NativeMenubar);
1604 return NS_OK;
1605}
1606
1607NS_IMETHODIMPnsresult
1608nsXULAppInfo::GetContentThemeDerivedColorSchemeIsDark(bool* aResult) {
1609 *aResult =
1610 PreferenceSheet::ThemeDerivedColorSchemeForContent() == ColorScheme::Dark;
1611 return NS_OK;
1612}
1613
1614NS_IMETHODIMPnsresult
1615nsXULAppInfo::GetPrefersReducedMotion(bool* aResult) {
1616 *aResult =
1617 LookAndFeel::GetInt(LookAndFeel::IntID::PrefersReducedMotion, 0) == 1;
1618 return NS_OK;
1619}
1620
1621NS_IMETHODIMPnsresult
1622nsXULAppInfo::GetDrawInTitlebar(bool* aResult) {
1623 *aResult = LookAndFeel::DrawInTitlebar();
1624 return NS_OK;
1625}
1626
1627NS_IMETHODIMPnsresult
1628nsXULAppInfo::GetCaretBlinkCount(int32_t* aResult) {
1629 *aResult = LookAndFeel::CaretBlinkCount();
1630 return NS_OK;
1631}
1632
1633NS_IMETHODIMPnsresult
1634nsXULAppInfo::GetCaretBlinkTime(int32_t* aResult) {
1635 *aResult = LookAndFeel::CaretBlinkTime();
1636 return NS_OK;
1637}
1638
1639NS_IMETHODIMPnsresult
1640nsXULAppInfo::GetDesktopEnvironment(nsACString& aDesktopEnvironment) {
1641#ifdef MOZ_WIDGET_GTK1
1642 aDesktopEnvironment.Assign(GetDesktopEnvironmentIdentifier());
1643#endif
1644 return NS_OK;
1645}
1646
1647NS_IMETHODIMPnsresult
1648nsXULAppInfo::GetIsWayland(bool* aResult) {
1649#ifdef MOZ_WIDGET_GTK1
1650 *aResult = GdkIsWaylandDisplay();
1651#else
1652 *aResult = false;
1653#endif
1654 return NS_OK;
1655}
1656
1657NS_IMETHODIMPnsresult
1658nsXULAppInfo::GetProcessStartupShortcut(nsAString& aShortcut) {
1659#if defined(XP_WIN)
1660 if (XRE_IsParentProcess()) {
1661 aShortcut.Assign(gProcessStartupShortcut);
1662 return NS_OK;
1663 }
1664#endif
1665 return NS_ERROR_NOT_AVAILABLE;
1666}
1667
1668#if defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
1669// Forward declaration
1670void SetupLauncherProcessPref();
1671
1672static Maybe<LauncherRegistryInfo::EnabledState> gLauncherProcessState;
1673#endif // defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
1674
1675NS_IMETHODIMPnsresult
1676nsXULAppInfo::GetLauncherProcessState(uint32_t* aResult) {
1677#if defined(XP_WIN) && defined(MOZ_LAUNCHER_PROCESS)
1678 SetupLauncherProcessPref();
1679
1680 if (!gLauncherProcessState) {
1681 return NS_ERROR_UNEXPECTED;
1682 }
1683
1684 *aResult = static_cast<uint32_t>(gLauncherProcessState.value());
1685 return NS_OK;
1686#else
1687 return NS_ERROR_NOT_AVAILABLE;
1688#endif
1689}
1690
1691#ifdef XP_WIN
1692NS_IMETHODIMPnsresult
1693nsXULAppInfo::GetUserCanElevate(bool* aUserCanElevate) {
1694 HANDLE rawToken;
1695 if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &rawToken)) {
1696 *aUserCanElevate = false;
1697 return NS_OK;
1698 }
1699
1700 nsAutoHandle token(rawToken);
1701 LauncherResult<TOKEN_ELEVATION_TYPE> elevationType = GetElevationType(token);
1702 if (elevationType.isErr()) {
1703 *aUserCanElevate = false;
1704 return NS_OK;
1705 }
1706
1707 // The possible values returned for elevationType and their meanings are:
1708 // TokenElevationTypeDefault: The token does not have a linked token
1709 // (e.g. UAC disabled or a standard user, so they can't be elevated)
1710 // TokenElevationTypeFull: The token is linked to an elevated token
1711 // (e.g. UAC is enabled and the user is already elevated so they can't
1712 // be elevated again)
1713 // TokenElevationTypeLimited: The token is linked to a limited token
1714 // (e.g. UAC is enabled and the user is not elevated, so they can be
1715 // elevated)
1716 *aUserCanElevate = (elevationType.inspect() == TokenElevationTypeLimited);
1717 return NS_OK;
1718}
1719#endif
1720
1721// Get the CrashReporter::Annotation referred to by the `aKey` string. This
1722// wraps `CrashReporter::AnnotationFromString` to assert the annotation string
1723// is valid in debug builds, and otherwise returns an NS_ERROR_INVALID_ARG if
1724// it is invalid.
1725static Result<CrashReporter::Annotation, nsresult> GetCrashAnnotation(
1726 const nsACString& aKey) {
1727 auto maybeAnnotation = CrashReporter::AnnotationFromString(aKey);
1728#ifdef DEBUG1
1729 if (!maybeAnnotation.isSome()) {
1730 std::string warning = "Annotation identifier not found: \"";
1731 warning += aKey.View();
1732 warning += "\"";
1733 NS_WARNING(warning.c_str())NS_DebugBreak(NS_DEBUG_WARNING, warning.c_str(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1733)
;
1734 }
1735 if (!StaticPrefs::toolkit_crash_annotation_testing_validation()) {
1736 MOZ_ASSERT(maybeAnnotation.isSome(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeAnnotation.isSome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeAnnotation.isSome()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeAnnotation.isSome()"
" (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1738
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeAnnotation.isSome()"
") (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")"); do { MOZ_CrashSequence(__null, 1738); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1737 "Invalid annotation identifier; ensure it exists in "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeAnnotation.isSome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeAnnotation.isSome()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeAnnotation.isSome()"
" (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1738
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeAnnotation.isSome()"
") (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")"); do { MOZ_CrashSequence(__null, 1738); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1738 "CrashAnnotations.yaml")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(maybeAnnotation.isSome())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(maybeAnnotation.isSome()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("maybeAnnotation.isSome()"
" (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1738
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "maybeAnnotation.isSome()"
") (" "Invalid annotation identifier; ensure it exists in " "CrashAnnotations.yaml"
")"); do { MOZ_CrashSequence(__null, 1738); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1739 }
1740#endif
1741 NS_ENSURE_TRUE(maybeAnnotation.isSome(), Err(NS_ERROR_INVALID_ARG))do { if ((__builtin_expect(!!(!(maybeAnnotation.isSome())), 0
))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "maybeAnnotation.isSome()"
") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1741); return Err(NS_ERROR_INVALID_ARG); } } while (false)
;
1742 return maybeAnnotation.extract();
1743}
1744
1745NS_IMETHODIMPnsresult
1746nsXULAppInfo::GetCrashReporterEnabled(bool* aEnabled) {
1747 *aEnabled = CrashReporter::GetEnabled();
1748 return NS_OK;
1749}
1750
1751NS_IMETHODIMPnsresult
1752nsXULAppInfo::SetEnabled(bool aEnabled) {
1753 if (aEnabled) {
1754 if (CrashReporter::GetEnabled()) {
1755 // no point in erroring for double-enabling
1756 return NS_OK;
1757 }
1758
1759 nsCOMPtr<nsIFile> greBinDir;
1760 NS_GetSpecialDirectory(NS_GRE_BIN_DIR"GreBinD", getter_AddRefs(greBinDir));
1761 if (!greBinDir) {
1762 return NS_ERROR_FAILURE;
1763 }
1764
1765 nsCOMPtr<nsIFile> xreBinDirectory = greBinDir;
1766 if (!xreBinDirectory) {
1767 return NS_ERROR_FAILURE;
1768 }
1769
1770 nsresult rv = CrashReporter::OOPInit(xreBinDirectory, true);
1771 if (rv != NS_OK) {
1772 return rv;
1773 }
1774
1775 return CrashReporter::SetExceptionHandler(xreBinDirectory, true);
1776 }
1777
1778 if (!CrashReporter::GetEnabled()) {
1779 // no point in erroring for double-disabling
1780 return NS_OK;
1781 }
1782
1783 nsresult rv = CrashReporter::UnsetExceptionHandler();
1784#if !defined(MOZ_WIDGET_ANDROID)
1785 // Don't deinit on Android as we can't get back up again
1786 // (bug 2040673 comment 20).
1787 // TODO: Fix it
1788 CrashReporter::OOPDeinit();
1789#endif
1790 return rv;
1791}
1792
1793NS_IMETHODIMPnsresult
1794nsXULAppInfo::GetServerURL(nsIURL** aServerURL) {
1795 NS_ENSURE_ARG_POINTER(aServerURL)do { if ((__builtin_expect(!!(!(aServerURL)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aServerURL" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 1795
); return NS_ERROR_INVALID_POINTER; } } while (false)
;
1796 if (!CrashReporter::GetEnabled()) return NS_ERROR_NOT_INITIALIZED;
1797
1798 nsAutoCString data;
1799 if (!CrashReporter::GetServerURL(data)) {
1800 return NS_ERROR_FAILURE;
1801 }
1802 nsCOMPtr<nsIURI> uri;
1803 NS_NewURI(getter_AddRefs(uri), data);
1804 if (!uri) return NS_ERROR_FAILURE;
1805
1806 nsCOMPtr<nsIURL> url;
1807 url = do_QueryInterface(uri);
1808 NS_ADDREF(*aServerURL = url)(*aServerURL = url)->AddRef();
1809
1810 return NS_OK;
1811}
1812
1813NS_IMETHODIMPnsresult
1814nsXULAppInfo::SetServerURL(nsIURL* aServerURL) {
1815 // Only allow https or http URLs
1816 if (!net::SchemeIsHttpOrHttps(aServerURL)) {
1817 return NS_ERROR_INVALID_ARG;
1818 }
1819
1820 nsAutoCString spec;
1821 nsresult rv = aServerURL->GetSpec(spec);
1822 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1822); return rv; } } while (false)
;
1823
1824 return CrashReporter::SetServerURL(spec);
1825}
1826
1827NS_IMETHODIMPnsresult
1828nsXULAppInfo::GetMinidumpPath(nsIFile** aMinidumpPath) {
1829 if (!CrashReporter::GetEnabled()) {
1830 return NS_ERROR_NOT_INITIALIZED;
1831 }
1832
1833 nsAutoString path;
1834 if (!CrashReporter::GetMinidumpPath(path)) {
1835 return NS_ERROR_FAILURE;
1836 }
1837
1838 return NS_NewLocalFile(path, aMinidumpPath);
1839}
1840
1841NS_IMETHODIMPnsresult
1842nsXULAppInfo::SetMinidumpPath(nsIFile* aMinidumpPath) {
1843 nsAutoString path;
1844 nsresult rv = aMinidumpPath->GetPath(path);
1845 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1845); return rv; } } while (false)
;
1846 return CrashReporter::SetMinidumpPath(path);
1847}
1848
1849NS_IMETHODIMPnsresult
1850nsXULAppInfo::GetMinidumpForID(const nsAString& aId, nsIFile** aMinidump) {
1851 if (!CrashReporter::GetMinidumpForID(aId, aMinidump)) {
1852 return NS_ERROR_FILE_NOT_FOUND;
1853 }
1854
1855 return NS_OK;
1856}
1857
1858NS_IMETHODIMPnsresult
1859nsXULAppInfo::GetExtraFileForID(const nsAString& aId, nsIFile** aExtraFile) {
1860 if (!CrashReporter::GetExtraFileForID(aId, aExtraFile)) {
1861 return NS_ERROR_FILE_NOT_FOUND;
1862 }
1863
1864 return NS_OK;
1865}
1866
1867NS_IMETHODIMPnsresult
1868nsXULAppInfo::AnnotateCrashReport(const nsACString& key,
1869 JS::Handle<JS::Value> data, JSContext* cx) {
1870 CrashReporter::Annotation annotation = MOZ_TRY(GetCrashAnnotation(key))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(GetCrashAnnotation(key)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
1871 switch (data.type()) {
1872 case JS::ValueType::Int32:
1873 CrashReporter::RecordAnnotationU32(annotation, data.toInt32());
1874 break;
1875 case JS::ValueType::Boolean:
1876 CrashReporter::RecordAnnotationBool(annotation, data.toBoolean());
1877 break;
1878 case JS::ValueType::String: {
1879 JSString* value = data.toString();
1880 size_t length = (JS_GetStringLength(value) * 3) + 1;
1881 nsCString buffer;
1882 auto res = JS_EncodeStringToUTF8BufferPartial(
1883 cx, value, buffer.GetMutableData(length));
1884
1885 if (!res) {
1886 return NS_ERROR_OUT_OF_MEMORY;
1887 }
1888
1889 size_t written;
1890 std::tie(std::ignore, written) = *res;
1891
1892 buffer.SetLength(written);
1893
1894 CrashReporter::RecordAnnotationNSCString(annotation, buffer);
1895 } break;
1896 default:
1897 return NS_ERROR_INVALID_ARG;
1898 }
1899 return NS_OK;
1900}
1901
1902NS_IMETHODIMPnsresult
1903nsXULAppInfo::RemoveCrashReportAnnotation(const nsACString& key) {
1904 CrashReporter::Annotation annotation = MOZ_TRY(GetCrashAnnotation(key))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(GetCrashAnnotation(key)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
1905 CrashReporter::UnrecordAnnotation(annotation);
1906 return NS_OK;
1907}
1908
1909NS_IMETHODIMPnsresult
1910nsXULAppInfo::IsAnnotationValid(const nsACString& aValue, bool* aIsValid) {
1911 auto annotation = CrashReporter::AnnotationFromString(aValue);
1912 *aIsValid = annotation.isSome();
1913 return NS_OK;
1914}
1915
1916NS_IMETHODIMPnsresult
1917nsXULAppInfo::IsAnnotationAllowedForReport(const nsACString& aValue,
1918 bool* aIsAllowed) {
1919 CrashReporter::Annotation annotation = MOZ_TRY(GetCrashAnnotation(aValue))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(GetCrashAnnotation(aValue)); if ((__builtin_expect(!!(mozTryVarTempResult
.isErr()), 0))) { return mozTryVarTempResult.propagateErr(); }
mozTryVarTempResult.unwrap(); })
;
1920 *aIsAllowed = CrashReporter::IsAnnotationAllowedForReport(annotation);
1921 return NS_OK;
1922}
1923
1924NS_IMETHODIMPnsresult
1925nsXULAppInfo::AppendAppNotesToCrashReport(const nsACString& data) {
1926 return CrashReporter::AppendAppNotesToCrashReport(data);
1927}
1928
1929NS_IMETHODIMPnsresult
1930nsXULAppInfo::WriteMinidumpForException(void* aExceptionInfo) {
1931#ifdef XP_WIN
1932 return CrashReporter::WriteMinidumpForException(
1933 static_cast<EXCEPTION_POINTERS*>(aExceptionInfo));
1934#else
1935 return NS_ERROR_NOT_IMPLEMENTED;
1936#endif
1937}
1938
1939NS_IMETHODIMPnsresult
1940nsXULAppInfo::AppendObjCExceptionInfoToAppNotes(void* aException) {
1941#ifdef XP_MACOSX
1942 return CrashReporter::AppendObjCExceptionInfoToAppNotes(aException);
1943#else
1944 return NS_ERROR_NOT_IMPLEMENTED;
1945#endif
1946}
1947
1948NS_IMETHODIMPnsresult
1949nsXULAppInfo::GetSubmitReports(bool* aEnabled) {
1950 return CrashReporter::GetSubmitReports(aEnabled);
1951}
1952
1953NS_IMETHODIMPnsresult
1954nsXULAppInfo::SetSubmitReports(bool aEnabled) {
1955 return CrashReporter::SetSubmitReports(aEnabled);
1956}
1957
1958NS_IMETHODIMPnsresult
1959nsXULAppInfo::UpdateCrashEventsDir() {
1960 CrashReporter::UpdateCrashEventsDir();
1961 return NS_OK;
1962}
1963
1964NS_IMETHODIMPnsresult
1965nsXULAppInfo::SaveMemoryReport() {
1966 if (!CrashReporter::GetEnabled()) {
1967 return NS_ERROR_NOT_INITIALIZED;
1968 }
1969 nsCOMPtr<nsIFile> file;
1970 nsresult rv = CrashReporter::GetDefaultMemoryReportFile(getter_AddRefs(file));
1971 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1971)
) {
1972 return rv;
1973 }
1974
1975 nsString path;
1976 file->GetPath(path);
1977
1978 nsCOMPtr<nsIMemoryInfoDumper> dumper =
1979 do_GetService("@mozilla.org/memory-info-dumper;1");
1980 if (NS_WARN_IF(!dumper)NS_warn_if_impl(!dumper, "!dumper", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1980)
) {
1981 return NS_ERROR_UNEXPECTED;
1982 }
1983
1984 rv = dumper->DumpMemoryReportsToNamedFile(
1985 path, this, file, true /* anonymize */, false /* minimizeMemoryUsage */);
1986 if (NS_WARN_IF(NS_FAILED(rv))NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))), "NS_FAILED(rv)", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1986)
) {
1987 return rv;
1988 }
1989 return NS_OK;
1990}
1991
1992// This method is from nsIFInishDumpingCallback.
1993NS_IMETHODIMPnsresult
1994nsXULAppInfo::Callback(nsISupports* aData) {
1995 nsCOMPtr<nsIFile> file = do_QueryInterface(aData);
1996 MOZ_ASSERT(file)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(file)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(file))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("file", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 1996); AnnotateMozCrashReason("MOZ_ASSERT" "(" "file" ")");
do { MOZ_CrashSequence(__null, 1996); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1997
1998 CrashReporter::SetMemoryReportFile(file);
1999 return NS_OK;
2000}
2001
2002static const nsXULAppInfo kAppInfo;
2003namespace mozilla {
2004nsresult AppInfoConstructor(REFNSIIDconst nsIID& aIID, void** aResult) {
2005 return const_cast<nsXULAppInfo*>(&kAppInfo)->QueryInterface(aIID, aResult);
2006}
2007} // namespace mozilla
2008
2009bool gLogConsoleErrors = false;
2010
2011#define NS_ENSURE_TRUE_LOG(x, ret)do { if ((__builtin_expect(!!(!(x)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "x" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2011); gLogConsoleErrors = true; return ret; } } while (0)
\
2012 PR_BEGIN_MACROdo { \
2013 if (MOZ_UNLIKELY(!(x))(__builtin_expect(!!(!(x)), 0))) { \
2014 NS_WARNING("NS_ENSURE_TRUE(" #x ") failed")NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" #x ") failed"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
2014)
; \
2015 gLogConsoleErrors = true; \
2016 return ret; \
2017 } \
2018 PR_END_MACRO} while (0)
2019
2020#define NS_ENSURE_SUCCESS_LOG(res, ret)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(res)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(res)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2020); gLogConsoleErrors = true; return ret; } } while (0)
\
2021 NS_ENSURE_TRUE_LOG(NS_SUCCEEDED(res), ret)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(res)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(res)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2021); gLogConsoleErrors = true; return ret; } } while (0)
2022
2023/**
2024 * Because we're starting/stopping XPCOM several times in different scenarios,
2025 * this class is a stack-based critter that makes sure that XPCOM is shut down
2026 * during early returns.
2027 */
2028
2029class ScopedXPCOMStartup {
2030 public:
2031 ScopedXPCOMStartup() : mServiceManager(nullptr) {}
2032 ~ScopedXPCOMStartup();
2033
2034 nsresult Initialize(bool aInitJSContext = true);
2035 nsresult SetWindowCreator(nsINativeAppSupport* native);
2036
2037 private:
2038 nsIServiceManager* mServiceManager;
2039 static nsINativeAppSupport* gNativeAppSupport;
2040
2041 friend already_AddRefed<nsINativeAppSupport> NS_GetNativeAppSupport();
2042};
2043
2044ScopedXPCOMStartup::~ScopedXPCOMStartup() {
2045 NS_IF_RELEASE(gNativeAppSupport)do { if (gNativeAppSupport) { (gNativeAppSupport)->Release
(); (gNativeAppSupport) = 0; } } while (0)
;
2046
2047 if (mServiceManager) {
2048#ifdef XP_MACOSX
2049 // On OS X, we need a pool to catch cocoa objects that are autoreleased
2050 // during teardown.
2051 mozilla::MacAutoreleasePool pool;
2052#endif
2053
2054 nsCOMPtr<nsIAppStartup> appStartup(components::AppStartup::Service());
2055 if (appStartup) appStartup->DestroyHiddenWindow();
2056
2057 gDirServiceProvider->DoShutdown();
2058 PROFILER_MARKER_UNTYPED("Shutdown early", OTHER)do { ; do { if (profiler_is_collecting_markers()) { ::profiler_add_marker_impl
("Shutdown early", ::geckoprofiler::category::OTHER); } } while
(false); } while (false)
;
2059
2060 WriteConsoleLog();
2061
2062 NS_ShutdownXPCOM(mServiceManager);
2063 mServiceManager = nullptr;
2064 }
2065}
2066
2067nsresult ScopedXPCOMStartup::Initialize(bool aInitJSContext) {
2068 NS_ASSERTION(gDirServiceProvider, "Should not get here!")do { if (!(gDirServiceProvider)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Should not get here!", "gDirServiceProvider", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2068); MOZ_PretendNoReturn(); } } while (0)
;
2069
2070 nsresult rv;
2071
2072 rv = NS_InitXPCOM(&mServiceManager, gDirServiceProvider->GetAppDir(),
2073 gDirServiceProvider, aInitJSContext);
2074 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2075 NS_ERROR("Couldn't start xpcom!")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Couldn't start xpcom!"
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
2075); MOZ_PretendNoReturn(); } while (0)
;
2076 mServiceManager = nullptr;
2077 } else {
2078#ifdef DEBUG1
2079 nsCOMPtr<nsIComponentRegistrar> reg = do_QueryInterface(mServiceManager);
2080 NS_ASSERTION(reg, "Service Manager doesn't QI to Registrar.")do { if (!(reg)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Service Manager doesn't QI to Registrar."
, "reg", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2080
); MOZ_PretendNoReturn(); } } while (0)
;
2081#endif
2082 }
2083
2084 return rv;
2085}
2086
2087/**
2088 * This is a little factory class that serves as a singleton-service-factory
2089 * for the nativeappsupport object.
2090 */
2091class nsSingletonFactory final : public nsIFactory {
2092 public:
2093 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
2094 NS_DECL_NSIFACTORYvirtual nsresult CreateInstance(const nsIID & iid, void *
* result) override;
2095
2096 explicit nsSingletonFactory(nsISupports* aSingleton);
2097
2098 private:
2099 ~nsSingletonFactory() = default;
2100 nsCOMPtr<nsISupports> mSingleton;
2101};
2102
2103nsSingletonFactory::nsSingletonFactory(nsISupports* aSingleton)
2104 : mSingleton(aSingleton) {
2105 NS_ASSERTION(mSingleton, "Singleton was null!")do { if (!(mSingleton)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Singleton was null!"
, "mSingleton", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2105); MOZ_PretendNoReturn(); } } while (0)
;
2106}
2107
2108NS_IMPL_ISUPPORTS(nsSingletonFactory, nsIFactory)MozExternalRefCountType nsSingletonFactory::AddRef(void) { static_assert
(!std::is_destructible_v<nsSingletonFactory>, "Reference-counted class "
"nsSingletonFactory" " should not have a public destructor. "
"Make this class's destructor non-public"); do { static_assert
( mozilla::detail::AssertionConditionType<decltype(int32_t
(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2108); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 2108
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsSingletonFactory" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsSingletonFactory" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsSingletonFactory\" != nullptr" " (" "Must specify a name"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2108
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsSingletonFactory\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2108); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsSingletonFactory" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("nsSingletonFactory"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
nsSingletonFactory::Release(void) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(int32_t(mRefCnt)
> 0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2108
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 2108
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("nsSingletonFactory" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("nsSingletonFactory" != nullptr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"\"nsSingletonFactory\" != nullptr" " (" "Must specify a name"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2108
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"nsSingletonFactory\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2108); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("nsSingletonFactory" " not thread-safe"); const
char* const nametmp = "nsSingletonFactory"; nsrefcnt count =
--mRefCnt; NS_LogRelease((this), (count), (nametmp)); if (count
== 0) { mRefCnt = 1; delete (this); return 0; } return count
; } nsresult nsSingletonFactory::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2108); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<nsSingletonFactory, nsIFactory>, int32_t
( reinterpret_cast<char*>(static_cast<nsIFactory*>
((nsSingletonFactory*)0x1000)) - reinterpret_cast<char*>
((nsSingletonFactory*)0x1000))}, {&mozilla::detail::kImplementedIID
<nsSingletonFactory, nsISupports>, int32_t(reinterpret_cast
<char*>(static_cast<nsISupports*>( static_cast<
nsIFactory*>((nsSingletonFactory*)0x1000))) - reinterpret_cast
<char*>((nsSingletonFactory*)0x1000))}, { nullptr, 0 } }
; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); return rv; }
2109
2110NS_IMETHODIMPnsresult
2111nsSingletonFactory::CreateInstance(const nsIID& aIID, void** aResult) {
2112 return mSingleton->QueryInterface(aIID, aResult);
2113}
2114
2115/**
2116 * Set our windowcreator on the WindowWatcher service.
2117 */
2118nsresult ScopedXPCOMStartup::SetWindowCreator(nsINativeAppSupport* native) {
2119 nsresult rv;
2120
2121 NS_IF_ADDREF(gNativeAppSupport = native)ns_if_addref(gNativeAppSupport = native);
2122
2123 nsCOMPtr<nsIWindowCreator> creator(components::AppStartup::Service());
2124 if (!creator) return NS_ERROR_UNEXPECTED;
2125
2126 nsCOMPtr<nsIWindowWatcher> wwatch(
2127 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1", &rv));
2128 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2128); return rv; } } while (false)
;
2129
2130 return wwatch->SetWindowCreator(creator);
2131}
2132
2133/* static */ already_AddRefed<nsINativeAppSupport> NS_GetNativeAppSupport() {
2134 if (!ScopedXPCOMStartup::gNativeAppSupport) {
2135 return nullptr;
2136 }
2137
2138 return do_AddRef(ScopedXPCOMStartup::gNativeAppSupport);
2139}
2140
2141#ifdef MOZ_HAS_REMOTE1
2142/* static */ already_AddRefed<nsIRemoteService> GetRemoteService() {
2143 AssertIsOnMainThread();
2144
2145 if (!gRemoteService) {
2146 gRemoteService = new nsRemoteService();
2147 }
2148 nsCOMPtr<nsIRemoteService> remoteService = gRemoteService.get();
2149 return remoteService.forget();
2150}
2151#endif
2152
2153nsINativeAppSupport* ScopedXPCOMStartup::gNativeAppSupport;
2154
2155static void DumpArbitraryHelp() {
2156 nsresult rv;
2157
2158 ScopedLogging log;
2159
2160 {
2161 ScopedXPCOMStartup xpcom;
2162 xpcom.Initialize();
2163
2164 nsCOMPtr<nsICommandLineRunner> cmdline(new nsCommandLine());
2165
2166 nsCString text;
2167 rv = cmdline->GetHelpText(text);
2168 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) printf("%s", text.get());
2169 }
2170}
2171
2172// English text needs to go into a dtd file.
2173// But when this is called we have no components etc. These strings must either
2174// be here, or in a native resource file.
2175static void DumpHelp() {
2176 printf(
2177 "Usage: %s [ options ... ] [URL]\n"
2178 " where options include:\n\n",
2179 gArgv[0]);
2180
2181#ifdef MOZ_X111
2182 printf(
2183 "X11 options\n"
2184 " --display=DISPLAY X display to use\n"
2185 " --sync Make X calls synchronous\n");
2186#endif
2187#ifdef XP_UNIX1
2188 printf(
2189 " --g-fatal-warnings Make all warnings fatal\n"
2190 "\n%s options\n",
2191 (const char*)gAppData->name);
2192#endif
2193
2194 printf(
2195 " -h or --help Print this message.\n"
2196 " -v or --version Print %s version.\n"
2197 " --full-version Print %s version, build and platform build ids.\n"
2198 " -P <profile> Start with <profile>.\n"
2199 " --profile <path> Start with profile at <path>.\n"
2200 " --migration Start with migration wizard.\n"
2201 " --ProfileManager Start with ProfileManager.\n"
2202 " --origin-to-force-quic-on <origin>\n"
2203 " Force to use QUIC for the specified origin.\n"
2204#ifdef MOZ_HAS_REMOTE1
2205 " --new-instance Open new instance, not a new window in running "
2206 "instance.\n"
2207#endif
2208 " --safe-mode Disables extensions and themes for this session.\n"
2209#ifdef MOZ_BLOCK_PROFILE_DOWNGRADE1
2210 " --allow-downgrade Allows downgrading a profile.\n"
2211#endif
2212 " --MOZ_LOG=<modules> Treated as MOZ_LOG=<modules> environment "
2213 "variable,\n"
2214 " overrides it.\n"
2215 " --MOZ_LOG_FILE=<file> Treated as MOZ_LOG_FILE=<file> environment "
2216 "variable,\n"
2217 " overrides it. If MOZ_LOG_FILE is not specified as "
2218 "an\n"
2219 " argument or as an environment variable, logging "
2220 "will be\n"
2221 " written to stdout.\n",
2222 (const char*)gAppData->name, (const char*)gAppData->name);
2223
2224#if defined(XP_WIN)
2225 printf(" --console Start %s with a debugging console.\n",
2226 (const char*)gAppData->name);
2227#endif
2228
2229#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK1) || defined(XP_MACOSX)
2230 printf(" --headless Run without a GUI.\n");
2231#endif
2232
2233#if defined(MOZ_ENABLE_DBUS1)
2234 printf(
2235 " --dbus-service <launcher> Run as DBus service for "
2236 "org.freedesktop.Application and\n"
2237 " set a launcher (usually /usr/bin/appname "
2238 "script) for it.\n");
2239#endif
2240
2241 // this works, but only after the components have registered. so if you drop
2242 // in a new command line handler, --help won't not until the second run. out
2243 // of the bug, because we ship a component.reg file, it works correctly.
2244 DumpArbitraryHelp();
2245}
2246
2247static inline void DumpVersion() {
2248 if (gAppData->vendor && *gAppData->vendor) {
2249 printf("%s ", (const char*)gAppData->vendor);
2250 }
2251 printf("%s ", (const char*)gAppData->name);
2252
2253 // Use the displayed version
2254 // For example, for beta, we would display 42.0b2 instead of 42.0
2255 printf("%s", MOZ_STRINGIFY(MOZ_APP_VERSION_DISPLAY)"160.0a1");
2256
2257 if (gAppData->copyright && *gAppData->copyright) {
2258 printf(", %s", (const char*)gAppData->copyright);
2259 }
2260 printf("\n");
2261}
2262
2263static inline void DumpFullVersion() {
2264 if (gAppData->vendor && *gAppData->vendor) {
2265 printf("%s ", (const char*)gAppData->vendor);
2266 }
2267 printf("%s ", (const char*)gAppData->name);
2268
2269 // Use the displayed version
2270 // For example, for beta, we would display 42.0b2 instead of 42.0
2271 printf("%s ", MOZ_STRINGIFY(MOZ_APP_VERSION_DISPLAY)"160.0a1");
2272
2273 printf("%s ", (const char*)gAppData->buildID);
2274 printf("%s ", (const char*)PlatformBuildID());
2275 if (gAppData->copyright && *gAppData->copyright) {
2276 printf(", %s", (const char*)gAppData->copyright);
2277 }
2278 printf("\n");
2279}
2280
2281void XRE_InitOmnijar(nsIFile* greOmni, nsIFile* appOmni) {
2282 mozilla::Omnijar::Init(greOmni, appOmni);
2283}
2284
2285nsresult XRE_GetBinaryPath(nsIFile** aResult) {
2286 return mozilla::BinaryPath::GetFile(aResult);
2287}
2288
2289#ifdef XP_WIN
2290# include "nsWindowsRestart.cpp"
2291# include <shellapi.h>
2292
2293typedef BOOL(WINAPI* SetProcessDEPPolicyFunc)(DWORD dwFlags);
2294
2295static void RegisterApplicationRestartChanged(const char* aPref, void* aData) {
2296 DWORD cchCmdLine = 0;
2297 HRESULT rc = ::GetApplicationRestartSettings(::GetCurrentProcess(), nullptr,
2298 &cchCmdLine, nullptr);
2299 bool wasRegistered = false;
2300 if (rc == S_OK) {
2301 wasRegistered = true;
2302 }
2303
2304 if (Preferences::GetBool(PREF_WIN_REGISTER_APPLICATION_RESTART, false) &&
2305 !wasRegistered) {
2306 // Make the command line to use when restarting.
2307 // Excludes argv[0] because RegisterApplicationRestart adds the
2308 // executable name, replace that temporarily with -os-restarted
2309 char* exeName = gRestartArgv[0];
2310 gRestartArgv[0] = const_cast<char*>("-os-restarted");
2311 wchar_t** restartArgvConverted =
2312 AllocConvertUTF8toUTF16Strings(gRestartArgc, gRestartArgv);
2313 gRestartArgv[0] = exeName;
2314
2315 mozilla::UniquePtr<wchar_t[]> restartCommandLine;
2316 if (restartArgvConverted) {
2317 restartCommandLine =
2318 mozilla::MakeCommandLine(gRestartArgc, restartArgvConverted);
2319 FreeAllocStrings(gRestartArgc, restartArgvConverted);
2320 }
2321
2322 if (restartCommandLine) {
2323 // Flags RESTART_NO_PATCH and RESTART_NO_REBOOT are not set, so we
2324 // should be restarted if terminated by an update or restart.
2325 ::RegisterApplicationRestart(restartCommandLine.get(),
2326 RESTART_NO_CRASH | RESTART_NO_HANG);
2327 }
2328 } else if (wasRegistered) {
2329 ::UnregisterApplicationRestart();
2330 }
2331}
2332
2333static void OnAlteredPrefetchPrefChanged(const char* aPref, void* aData) {
2334 int32_t prefVal = Preferences::GetInt(PREF_WIN_ALTERED_DLL_PREFETCH, 0);
2335
2336 mozilla::DllPrefetchExperimentRegistryInfo prefetchRegInfo;
2337 mozilla::DebugOnly<mozilla::Result<Ok, nsresult>> reflectResult =
2338 prefetchRegInfo.ReflectPrefToRegistry(prefVal);
2339
2340 MOZ_ASSERT(reflectResult.value.isOk())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(reflectResult.value.isOk())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(reflectResult.value.isOk()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("reflectResult.value.isOk()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2340); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "reflectResult.value.isOk()" ")"); do { MOZ_CrashSequence
(__null, 2340); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2341}
2342
2343static void SetupAlteredPrefetchPref() {
2344 mozilla::DllPrefetchExperimentRegistryInfo prefetchRegInfo;
2345
2346 mozilla::DebugOnly<mozilla::Result<Ok, nsresult>> reflectResult =
2347 prefetchRegInfo.ReflectPrefToRegistry(
2348 Preferences::GetInt(PREF_WIN_ALTERED_DLL_PREFETCH, 0));
2349 MOZ_ASSERT(reflectResult.value.isOk())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(reflectResult.value.isOk())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(reflectResult.value.isOk()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("reflectResult.value.isOk()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2349); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "reflectResult.value.isOk()" ")"); do { MOZ_CrashSequence
(__null, 2349); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
2350
2351 Preferences::RegisterCallback(&OnAlteredPrefetchPrefChanged,
2352 PREF_WIN_ALTERED_DLL_PREFETCH);
2353}
2354
2355static LazyLogModule gSkeletonLog("PreXULSkeletonUI");
2356# define SKELETON_LOG(str, ...) \
2357 MOZ_LOG(gSkeletonLog, LogLevel::Debug, (str, ##__VA_ARGS__))do { const ::mozilla::LogModule* moz_real_module = gSkeletonLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, str, ##__VA_ARGS__); } } while (0)
2358static void ReflectSkeletonUIPrefToRegistry(const char* aPref, void* aData) {
2359 (void)aPref;
2360 (void)aData;
2361
2362 RefPtr<nsToolkitProfileService> mProfileSvc;
2363 mProfileSvc = NS_GetToolkitProfileService();
2364
2365 bool hasShowProfileSelector = mProfileSvc->HasShowProfileSelector();
2366 bool skeletonUIPref = StaticPrefs::browser_startup_preXulSkeletonUI();
2367 bool startupBlankWindowPref = StaticPrefs::browser_startup_blankWindow();
2368 bool drawInTitlebar = LookAndFeel::DrawInTitlebar();
2369 SKELETON_LOG(
2370 "ReflectSkeletonUIPrefToRegistry: hasShowProfileSelector %d, "
2371 "skeletonUIPref %d, startupBlankWindowPref %d, drawInTitlebar %d",
2372 hasShowProfileSelector ? 1 : 0, skeletonUIPref ? 1 : 0,
2373 startupBlankWindowPref ? 1 : 0, drawInTitlebar ? 1 : 0);
2374
2375 bool shouldBeEnabled = !hasShowProfileSelector && skeletonUIPref &&
2376 startupBlankWindowPref && drawInTitlebar;
2377 SKELETON_LOG("ReflectSkeletonUIPrefToRegistry: shouldBeEnabled %d",
2378 shouldBeEnabled ? 1 : 0);
2379 if (shouldBeEnabled && Preferences::HasUserValue(kPrefThemeId)) {
2380 nsCString themeId;
2381 Preferences::GetCString(kPrefThemeId, themeId);
2382 if (themeId.EqualsLiteral("default-theme@mozilla.org")) {
2383 (void)SetPreXULSkeletonUIThemeId(ThemeMode::Default);
2384 } else if (themeId.EqualsLiteral("firefox-compact-dark@mozilla.org")) {
2385 (void)SetPreXULSkeletonUIThemeId(ThemeMode::Dark);
2386 } else if (themeId.EqualsLiteral("firefox-compact-light@mozilla.org")) {
2387 (void)SetPreXULSkeletonUIThemeId(ThemeMode::Light);
2388 } else {
2389 SKELETON_LOG(
2390 "ReflectSkeletonUIPrefToRegistry: clearing shouldBeEnabled "
2391 "because of bad themeId %s",
2392 themeId.get());
2393 shouldBeEnabled = false;
2394 }
2395 } else if (shouldBeEnabled) {
2396 (void)SetPreXULSkeletonUIThemeId(ThemeMode::Default);
2397 }
2398
2399 SKELETON_LOG(
2400 "ReflectSkeletonUIPrefToRegistry: old enabled %d, new enabled "
2401 "%d",
2402 GetPreXULSkeletonUIEnabled() ? 1 : 0, shouldBeEnabled ? 1 : 0);
2403 if (GetPreXULSkeletonUIEnabled() != shouldBeEnabled) {
2404 (void)SetPreXULSkeletonUIEnabledIfAllowed(shouldBeEnabled);
2405 }
2406}
2407# undef SKELETON_LOG
2408
2409class ShowProfileSelectorObserver final : public nsIObserver {
2410 public:
2411 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
2412 NS_DECL_NSIOBSERVERvirtual nsresult Observe(nsISupports *aSubject, const char * aTopic
, const char16_t * aData) override;
2413
2414 ShowProfileSelectorObserver() = default;
2415
2416 protected:
2417 ~ShowProfileSelectorObserver() = default;
2418};
2419
2420NS_IMPL_ISUPPORTS(ShowProfileSelectorObserver, nsIObserver)MozExternalRefCountType ShowProfileSelectorObserver::AddRef(void
) { static_assert(!std::is_destructible_v<ShowProfileSelectorObserver
>, "Reference-counted class " "ShowProfileSelectorObserver"
" should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2420); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { MOZ_CrashSequence(__null, 2420
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ShowProfileSelectorObserver" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("ShowProfileSelectorObserver" != nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("\"ShowProfileSelectorObserver\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2420); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ShowProfileSelectorObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2420); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("ShowProfileSelectorObserver" " not thread-safe"
); nsrefcnt count = ++mRefCnt; NS_LogAddRef((this), (count), (
"ShowProfileSelectorObserver"), (uint32_t)(sizeof(*this))); return
count; } MozExternalRefCountType ShowProfileSelectorObserver
::Release(void) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) > 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) > 0))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0"
" (" "dup release" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2420); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { MOZ_CrashSequence(__null, 2420
); __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("ShowProfileSelectorObserver" != nullptr)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!("ShowProfileSelectorObserver" != nullptr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("\"ShowProfileSelectorObserver\" != nullptr"
" (" "Must specify a name" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2420); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"ShowProfileSelectorObserver\" != nullptr"
") (" "Must specify a name" ")"); do { MOZ_CrashSequence(__null
, 2420); __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("ShowProfileSelectorObserver" " not thread-safe"
); const char* const nametmp = "ShowProfileSelectorObserver";
nsrefcnt count = --mRefCnt; NS_LogRelease((this), (count), (
nametmp)); if (count == 0) { mRefCnt = 1; delete (this); return
0; } return count; } nsresult ShowProfileSelectorObserver::QueryInterface
(const nsIID& aIID, void** aInstancePtr) { do { if (!(aInstancePtr
)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2420); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<ShowProfileSelectorObserver, nsIObserver
>, int32_t( reinterpret_cast<char*>(static_cast<nsIObserver
*>((ShowProfileSelectorObserver*)0x1000)) - reinterpret_cast
<char*>((ShowProfileSelectorObserver*)0x1000))}, {&
mozilla::detail::kImplementedIID<ShowProfileSelectorObserver
, nsISupports>, int32_t(reinterpret_cast<char*>(static_cast
<nsISupports*>( static_cast<nsIObserver*>((ShowProfileSelectorObserver
*)0x1000))) - reinterpret_cast<char*>((ShowProfileSelectorObserver
*)0x1000))}, { nullptr, 0 } } ; static_assert(std::size(table
) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
;
2421
2422NS_IMETHODIMPnsresult
2423ShowProfileSelectorObserver::Observe(nsISupports* aSubject, const char* aTopic,
2424 const char16_t* aData) {
2425 (void)aSubject;
2426 (void)aData;
2427 if (!strcmp(aTopic, "profile-show-selector-changed")) {
2428 ReflectSkeletonUIPrefToRegistry(nullptr, nullptr);
2429 }
2430
2431 return NS_OK;
2432}
2433
2434# if defined(MOZ_DEFAULT_BROWSER_AGENT)
2435
2436static void SetupSkeletonUIPrefs() {
2437 ReflectSkeletonUIPrefToRegistry(nullptr, nullptr);
2438 Preferences::RegisterCallback(&ReflectSkeletonUIPrefToRegistry,
2439 kPrefPreXulSkeletonUI);
2440 Preferences::RegisterCallback(&ReflectSkeletonUIPrefToRegistry,
2441 kPrefBrowserStartupBlankWindow);
2442 Preferences::RegisterCallback(&ReflectSkeletonUIPrefToRegistry, kPrefThemeId);
2443 Preferences::RegisterCallback(
2444 &ReflectSkeletonUIPrefToRegistry,
2445 nsDependentCString(StaticPrefs::GetPrefName_browser_tabs_inTitlebar()));
2446 nsCOMPtr<nsIObserverService> obsService =
2447 mozilla::services::GetObserverService();
2448 nsCOMPtr<nsIObserver> obs = new ShowProfileSelectorObserver();
2449 obsService->AddObserver(obs, "profile-show-selector-changed", false);
2450}
2451
2452# endif // defined(MOZ_DEFAULT_BROWSER_AGENT)
2453
2454# if defined(MOZ_LAUNCHER_PROCESS)
2455
2456static void OnLauncherPrefChanged(const char* aPref, void* aData) {
2457 bool prefVal = Preferences::GetBool(PREF_WIN_LAUNCHER_PROCESS_ENABLED, true);
2458
2459 mozilla::LauncherRegistryInfo launcherRegInfo;
2460 mozilla::DebugOnly<mozilla::LauncherVoidResult> reflectResult =
2461 launcherRegInfo.ReflectPrefToRegistry(prefVal);
2462 MOZ_ASSERT(reflectResult.inspect().isOk())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(reflectResult.inspect().isOk())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(reflectResult.inspect().isOk
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("reflectResult.inspect().isOk()", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2462); AnnotateMozCrashReason("MOZ_ASSERT" "(" "reflectResult.inspect().isOk()"
")"); do { MOZ_CrashSequence(__null, 2462); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2463}
2464
2465static void OnLauncherTelemetryPrefChanged(const char* aPref, void* aData) {
2466 bool prefVal = Preferences::GetBool(kPrefHealthReportUploadEnabled, true);
2467
2468 mozilla::LauncherRegistryInfo launcherRegInfo;
2469 mozilla::DebugOnly<mozilla::LauncherVoidResult> reflectResult =
2470 launcherRegInfo.ReflectTelemetryPrefToRegistry(prefVal);
2471 MOZ_ASSERT(reflectResult.inspect().isOk())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(reflectResult.inspect().isOk())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(reflectResult.inspect().isOk
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("reflectResult.inspect().isOk()", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2471); AnnotateMozCrashReason("MOZ_ASSERT" "(" "reflectResult.inspect().isOk()"
")"); do { MOZ_CrashSequence(__null, 2471); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2472}
2473
2474static void SetupLauncherProcessPref() {
2475 if (gLauncherProcessState) {
2476 // We've already successfully run
2477 return;
2478 }
2479
2480 mozilla::LauncherRegistryInfo launcherRegInfo;
2481
2482 mozilla::LauncherResult<mozilla::LauncherRegistryInfo::EnabledState>
2483 enabledState = launcherRegInfo.IsEnabled();
2484
2485 if (enabledState.isOk()) {
2486 gLauncherProcessState = Some(enabledState.unwrap());
2487
2488 CrashReporter::RecordAnnotationU32(
2489 CrashReporter::Annotation::LauncherProcessState,
2490 static_cast<uint32_t>(enabledState.unwrap()));
2491
2492 // Reflect the launcher process registry state into user prefs
2493 Preferences::SetBool(
2494 PREF_WIN_LAUNCHER_PROCESS_ENABLED,
2495 enabledState.unwrap() !=
2496 mozilla::LauncherRegistryInfo::EnabledState::ForceDisabled);
2497 }
2498
2499 mozilla::DebugOnly<mozilla::LauncherVoidResult> reflectResult =
2500 launcherRegInfo.ReflectTelemetryPrefToRegistry(
2501 Preferences::GetBool(kPrefHealthReportUploadEnabled, true));
2502 MOZ_ASSERT(reflectResult.inspect().isOk())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(reflectResult.inspect().isOk())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(reflectResult.inspect().isOk
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("reflectResult.inspect().isOk()", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2502); AnnotateMozCrashReason("MOZ_ASSERT" "(" "reflectResult.inspect().isOk()"
")"); do { MOZ_CrashSequence(__null, 2502); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2503
2504 Preferences::RegisterCallback(&OnLauncherPrefChanged,
2505 PREF_WIN_LAUNCHER_PROCESS_ENABLED);
2506 Preferences::RegisterCallback(&OnLauncherTelemetryPrefChanged,
2507 kPrefHealthReportUploadEnabled);
2508}
2509
2510# endif // defined(MOZ_LAUNCHER_PROCESS)
2511
2512# if defined(MOZ_DEFAULT_BROWSER_AGENT)
2513
2514# define DEFAULT_BROWSER_AGENT_KEY_NAME \
2515 "SOFTWARE\\" MOZ_APP_VENDOR"Mozilla" "\\" MOZ_APP_NAME"firefox" "\\Default Browser Agent"
2516
2517static nsresult PrependRegistryValueName(nsAutoString& aValueName) {
2518 nsresult rv;
2519
2520 nsCOMPtr<nsIFile> binaryPath;
2521 rv = XRE_GetBinaryPath(getter_AddRefs(binaryPath));
2522 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2522); return rv; } } while (false)
;
2523
2524 nsCOMPtr<nsIFile> binaryDir;
2525 rv = binaryPath->GetParent(getter_AddRefs(binaryDir));
2526 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2526); return rv; } } while (false)
;
2527
2528 nsAutoString prefix;
2529 rv = binaryDir->GetPath(prefix);
2530 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2530); return rv; } } while (false)
;
2531
2532 prefix.AppendLiteral("|");
2533 aValueName.Insert(prefix, 0);
2534
2535 return NS_OK;
2536}
2537
2538static void OnDefaultAgentTelemetryPrefChanged(const char* aPref, void* aData) {
2539 nsresult rv;
2540 nsAutoString valueName;
2541 if (strcmp(aPref, kPrefHealthReportUploadEnabled) == 0) {
2542 valueName.AssignLiteral("DisableTelemetry");
2543 } else if (strcmp(aPref, kPrefDefaultAgentEnabled) == 0) {
2544 valueName.AssignLiteral("DisableDefaultBrowserAgent");
2545 } else {
2546 return;
2547 }
2548 rv = PrependRegistryValueName(valueName);
2549 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2549); return; } } while (false)
;
2550
2551 nsCOMPtr<nsIWindowsRegKey> regKey =
2552 do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
2553 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2553); return; } } while (false)
;
2554
2555 nsAutoString keyName;
2556 keyName.AppendLiteral(DEFAULT_BROWSER_AGENT_KEY_NAME);
2557 rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, keyName,
2558 nsIWindowsRegKey::ACCESS_WRITE);
2559
2560 bool prefVal = Preferences::GetBool(aPref, true);
2561
2562 // We're recording whether the pref is *disabled*, so invert the value.
2563 rv = regKey->WriteIntValue(valueName, prefVal ? 0 : 1);
2564 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2564); return; } } while (false)
;
2565}
2566
2567static void OnSetDefaultBrowserUserChoicePrefChanged(const char* aPref,
2568 void* aData) {
2569 nsresult rv;
2570 if (strcmp(aPref, kPrefSetDefaultBrowserUserChoicePref) != 0) {
2571 return;
2572 }
2573 nsAutoString valueName;
2574 valueName.AssignLiteral("SetDefaultBrowserUserChoice");
2575 rv = PrependRegistryValueName(valueName);
2576 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2576); return; } } while (false)
;
2577
2578 nsCOMPtr<nsIWindowsRegKey> regKey =
2579 do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
2580 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2580); return; } } while (false)
;
2581
2582 nsAutoString keyName;
2583 keyName.AppendLiteral(DEFAULT_BROWSER_AGENT_KEY_NAME);
2584 rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, keyName,
2585 nsIWindowsRegKey::ACCESS_WRITE);
2586
2587 bool prefVal = Preferences::GetBool(aPref, true);
2588
2589 rv = regKey->WriteIntValue(valueName, prefVal);
2590 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2590); return; } } while (false)
;
2591}
2592
2593static void OnDefaultAgentRemoteSettingsPrefChanged(const char* aPref,
2594 void* aData) {
2595 nsresult rv;
2596 nsAutoString valueName;
2597 if (strcmp(aPref, kPrefServicesSettingsServer) == 0) {
2598 valueName.AssignLiteral("ServicesSettingsServer");
2599 } else {
2600 return;
2601 }
2602 rv = PrependRegistryValueName(valueName);
2603 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2603); return; } } while (false)
;
2604
2605 nsCOMPtr<nsIWindowsRegKey> regKey =
2606 do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
2607 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2607); return; } } while (false)
;
2608
2609 nsAutoString keyName;
2610 keyName.AppendLiteral(DEFAULT_BROWSER_AGENT_KEY_NAME);
2611 rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, keyName,
2612 nsIWindowsRegKey::ACCESS_WRITE);
2613
2614 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2614); return; } } while (false)
;
2615
2616 nsAutoString prefVal;
2617 rv = Preferences::GetString(aPref, prefVal);
2618 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2619 return;
2620 }
2621
2622 if (prefVal.IsEmpty()) {
2623 rv = regKey->RemoveValue(valueName);
2624 } else {
2625 rv = regKey->WriteStringValue(valueName, prefVal);
2626 }
2627 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2627); return; } } while (false)
;
2628}
2629
2630static void SetDefaultAgentLastRunTime() {
2631 nsresult rv;
2632 nsAutoString valueName;
2633 valueName.AppendLiteral("AppLastRunTime");
2634 rv = PrependRegistryValueName(valueName);
2635 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2635); return; } } while (false)
;
2636
2637 nsCOMPtr<nsIWindowsRegKey> regKey =
2638 do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
2639 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2639); return; } } while (false)
;
2640
2641 nsAutoString keyName;
2642 keyName.AppendLiteral(DEFAULT_BROWSER_AGENT_KEY_NAME);
2643 rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, keyName,
2644 nsIWindowsRegKey::ACCESS_WRITE);
2645 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2645); return; } } while (false)
;
2646
2647 FILETIME fileTime;
2648 GetSystemTimeAsFileTime(&fileTime);
2649
2650 ULARGE_INTEGER integerTime;
2651 integerTime.u.LowPart = fileTime.dwLowDateTime;
2652 integerTime.u.HighPart = fileTime.dwHighDateTime;
2653
2654 rv = regKey->WriteInt64Value(valueName, integerTime.QuadPart);
2655 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2655); return; } } while (false)
;
2656}
2657
2658# endif // defined(MOZ_DEFAULT_BROWSER_AGENT)
2659
2660#endif // XP_WIN
2661
2662void UnlockProfile() {
2663 if (gProfileLock) {
2664 gProfileLock->Unlock();
2665 }
2666}
2667
2668nsresult LaunchChild(bool aBlankCommandLine, bool aTryExec) {
2669 // Restart this process by exec'ing it into the current process
2670 // if supported by the platform. Otherwise, use NSPR.
2671
2672 if (aBlankCommandLine) {
2673 gRestartArgc = 1;
2674 gRestartArgv[gRestartArgc] = nullptr;
2675 }
2676
2677 SaveToEnv("MOZ_LAUNCHED_CHILD=1");
2678#if defined(MOZ_LAUNCHER_PROCESS)
2679 SaveToEnv("MOZ_LAUNCHER_PROCESS=1");
2680#endif // defined(MOZ_LAUNCHER_PROCESS)
2681
2682#if !defined(MOZ_WIDGET_ANDROID) // Android has separate restart code.
2683# if defined(XP_MACOSX)
2684 InitializeMacApp();
2685 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv, true);
2686 LaunchMacApp(gRestartArgc, gRestartArgv);
2687# else
2688 nsCOMPtr<nsIFile> lf;
2689 nsresult rv = XRE_GetBinaryPath(getter_AddRefs(lf));
2690 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2691
2692# if defined(XP_WIN)
2693 nsAutoString exePath;
2694 rv = lf->GetPath(exePath);
2695 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2696
2697 HANDLE hProcess;
2698 if (!WinLaunchChild(exePath.get(), gRestartArgc, gRestartArgv, nullptr,
2699 &hProcess))
2700 return NS_ERROR_FAILURE;
2701 // Keep the current process around until the restarted process has created
2702 // its message queue, to avoid the launched process's windows being forced
2703 // into the background.
2704 mozilla::WaitForInputIdle(hProcess);
2705 ::CloseHandle(hProcess);
2706
2707# else
2708 nsAutoCString exePath;
2709 rv = lf->GetNativePath(exePath);
2710 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return rv;
2711
2712# if defined(XP_UNIX1)
2713 if (aTryExec) {
2714 execv(exePath.get(), gRestartArgv);
2715
2716 // If execv returns we know it's because it failed.
2717 return NS_ERROR_FAILURE;
2718 }
2719# endif
2720 if (PR_CreateProcessDetached(exePath.get(), gRestartArgv, nullptr, nullptr) ==
2721 PR_FAILURE) {
2722 return NS_ERROR_FAILURE;
2723 }
2724
2725 // Note that we don't know if the child process starts okay, if it
2726 // immediately returns non-zero then we may mask that by returning a zero
2727 // exit status.
2728
2729# endif // XP_WIN
2730# endif // XP_MACOSX
2731#endif // MOZ_WIDGET_ANDROID
2732
2733 return NS_ERROR_LAUNCHED_CHILD_PROCESS;
2734}
2735
2736static const char kProfileProperties[] =
2737 "chrome://mozapps/locale/profile/profileSelection.properties";
2738
2739namespace {
2740
2741/**
2742 * This class, instead of a raw nsresult, should be the return type of any
2743 * function called by SelectProfile that initializes XPCOM.
2744 */
2745class ReturnAbortOnError {
2746 public:
2747 MOZ_IMPLICIT ReturnAbortOnError(nsresult aRv) { mRv = ConvertRv(aRv); }
2748
2749 operator nsresult() { return mRv; }
2750
2751 private:
2752 inline nsresult ConvertRv(nsresult aRv) {
2753 if (NS_SUCCEEDED(aRv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aRv)), 1))) || aRv == NS_ERROR_LAUNCHED_CHILD_PROCESS) {
2754 return aRv;
2755 }
2756#ifdef MOZ_BACKGROUNDTASKS1
2757 // A background task that fails to lock its profile will return
2758 // NS_ERROR_UNEXPECTED and this will allow the task to exit with a
2759 // non-zero exit code.
2760 if (aRv == NS_ERROR_UNEXPECTED && BackgroundTasks::IsBackgroundTaskMode()) {
2761 return aRv;
2762 }
2763#endif
2764 return NS_ERROR_ABORT;
2765 }
2766
2767 nsresult mRv;
2768};
2769
2770} // namespace
2771
2772static nsresult ProfileMissingDialog(nsINativeAppSupport* aNative) {
2773#ifdef MOZ_WIDGET_ANDROID
2774 // We cannot really do anything this early during initialization, so we just
2775 // return as this is likely the effect of misconfiguration on the test side.
2776 // Non-test code paths cannot set the profile folder, which is always the
2777 // default one.
2778 Output(true, "Could not find profile folder.\n");
2779 return NS_ERROR_ABORT;
2780#else
2781# ifdef MOZ_BACKGROUNDTASKS1
2782 if (BackgroundTasks::IsBackgroundTaskMode()) {
2783 // We should never get to this point in background task mode.
2784 printf_stderr(
2785 "Could not determine any profile running in backgroundtask mode!\n");
2786 return NS_ERROR_ABORT;
2787 }
2788# endif // MOZ_BACKGROUNDTASKS
2789
2790 if (gfxPlatform::IsHeadless()) {
2791 // Nothing can dismiss a modal dialog in headless mode, so report the
2792 // failure on stderr and exit instead of spinning in the event loop.
2793 Output(true, "Could not find profile folder.\n");
2794 return NS_ERROR_ABORT;
2795 }
2796
2797 nsresult rv;
2798
2799 ScopedXPCOMStartup xpcom;
2800 rv = xpcom.Initialize();
2801 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2801); return rv; } } while (false)
;
2802
2803 rv = xpcom.SetWindowCreator(aNative);
2804 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2804); return
NS_ERROR_FAILURE; } } while (false)
;
2805
2806# ifdef XP_MACOSX
2807 InitializeMacApp();
2808# endif
2809
2810 { // extra scoping is needed so we release these components before xpcom
2811 // shutdown
2812 nsCOMPtr<nsIStringBundleService> sbs =
2813 mozilla::components::StringBundle::Service();
2814 NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sbs)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sbs" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2814); return NS_ERROR_FAILURE; } } while (false)
;
2815
2816 nsCOMPtr<nsIStringBundle> sb;
2817 sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
2818 NS_ENSURE_TRUE_LOG(sb, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sb)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sb" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2818); gLogConsoleErrors = true; return NS_ERROR_FAILURE; }
} while (0)
;
2819
2820 NS_ConvertUTF8toUTF16 appName(gAppData->name);
2821 AutoTArray<nsString, 2> params = {appName, appName};
2822
2823 // profileMissing
2824 nsAutoString missingMessage;
2825 rv = sb->FormatStringFromName("profileMissing", params, missingMessage);
2826 NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_ABORT", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2826); return
NS_ERROR_ABORT; } } while (false)
;
2827
2828 nsAutoString missingTitle;
2829 params.SetLength(1);
2830 rv = sb->FormatStringFromName("profileMissingTitle", params, missingTitle);
2831 NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_ABORT", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2831); return
NS_ERROR_ABORT; } } while (false)
;
2832
2833 nsCOMPtr<nsIPromptService> ps(do_GetService(NS_PROMPTSERVICE_CONTRACTID"@mozilla.org/prompter;1"));
2834 NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(ps)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "ps" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2834); return NS_ERROR_FAILURE; } } while (false)
;
2835
2836 ps->Alert(nullptr, missingTitle.get(), missingMessage.get());
2837
2838 return NS_ERROR_ABORT;
2839 }
2840#endif // MOZ_WIDGET_ANDROID
2841}
2842
2843// Shows the "encryption pref vs on-disk state" mismatch dialog and
2844// returns NS_ERROR_ABORT so the caller can exit cleanly. aMsgKey /
2845// aTitleKey select which of the two scenarios (encrypted-but-pref-off
2846// or pref-on-but-plaintext) is being reported.
2847static nsresult ProfileEncryptionMismatchDialog(const char* aMsgKey,
2848 const char* aTitleKey,
2849 nsINativeAppSupport* aNative) {
2850#ifdef MOZ_WIDGET_ANDROID
2851 Output(true, "Profile encryption state does not match launching build.\n");
2852 return NS_ERROR_ABORT;
2853#else
2854# ifdef MOZ_BACKGROUNDTASKS1
2855 if (BackgroundTasks::IsBackgroundTaskMode()) {
2856 printf_stderr(
2857 "Profile encryption state does not match launching build in "
2858 "backgroundtask mode\n");
2859 return NS_ERROR_ABORT;
2860 }
2861# endif // MOZ_BACKGROUNDTASKS
2862
2863 if (gfxPlatform::IsHeadless()) {
2864 // Nothing can dismiss a modal dialog in headless mode.
2865 Output(true, "Profile encryption state does not match launching build.\n");
2866 return NS_ERROR_ABORT;
2867 }
2868
2869 nsresult rv;
2870
2871 ScopedXPCOMStartup xpcom;
2872 rv = xpcom.Initialize();
2873 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2873); return rv; } } while (false)
;
2874
2875 rv = xpcom.SetWindowCreator(aNative);
2876 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2876); return
NS_ERROR_FAILURE; } } while (false)
;
2877
2878# ifdef XP_MACOSX
2879 InitializeMacApp();
2880# endif
2881
2882 { // extra scoping is needed so we release these components before xpcom
2883 // shutdown
2884 nsCOMPtr<nsIStringBundleService> sbs =
2885 mozilla::components::StringBundle::Service();
2886 NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sbs)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sbs" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2886); return NS_ERROR_FAILURE; } } while (false)
;
2887
2888 nsCOMPtr<nsIStringBundle> sb;
2889 sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
2890 NS_ENSURE_TRUE_LOG(sb, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sb)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sb" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2890); gLogConsoleErrors = true; return NS_ERROR_FAILURE; }
} while (0)
;
2891
2892 NS_ConvertUTF8toUTF16 appName(gAppData->name);
2893 AutoTArray<nsString, 3> params = {appName, appName, appName};
2894
2895 nsAutoString msg;
2896 rv = sb->FormatStringFromName(aMsgKey, params, msg);
2897 NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_ABORT", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2897); return
NS_ERROR_ABORT; } } while (false)
;
2898
2899 nsAutoString title;
2900 params.SetLength(1);
2901 rv = sb->FormatStringFromName(aTitleKey, params, title);
2902 NS_ENSURE_SUCCESS(rv, NS_ERROR_ABORT)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_ABORT", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2902); return
NS_ERROR_ABORT; } } while (false)
;
2903
2904 nsCOMPtr<nsIPromptService> ps(do_GetService(NS_PROMPTSERVICE_CONTRACTID"@mozilla.org/prompter;1"));
2905 NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(ps)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "ps" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2905); return NS_ERROR_FAILURE; } } while (false)
;
2906
2907 ps->Alert(nullptr, title.get(), msg.get());
2908 return NS_ERROR_ABORT;
2909 }
2910#endif // MOZ_WIDGET_ANDROID
2911}
2912
2913static ReturnAbortOnError ProfileLockedDialog(nsIFile* aProfileDir,
2914 nsIFile* aProfileLocalDir,
2915 nsIProfileUnlocker* aUnlocker,
2916 nsINativeAppSupport* aNative,
2917 nsIProfileLock** aResult) {
2918 nsresult rv;
2919
2920 // We aren't going to start this instance so we can unblock other instances
2921 // from starting up.
2922#if defined(MOZ_HAS_REMOTE1)
2923 gStartupLock = nullptr;
2924#endif
2925
2926 bool exists;
2927 aProfileDir->Exists(&exists);
2928 if (!exists) {
2929 return ProfileMissingDialog(aNative);
2930 }
2931
2932 ScopedXPCOMStartup xpcom;
2933 rv = xpcom.Initialize();
2934 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2934); return rv; } } while (false)
;
2935
2936#if defined(MOZ_TELEMETRY_REPORTING)
2937 // We cannot check if telemetry has been disabled by the user, yet.
2938 // So, rely on the build time settings, instead.
2939 mozilla::Telemetry::WriteFailedProfileLock(aProfileDir);
2940#endif
2941
2942 rv = xpcom.SetWindowCreator(aNative);
2943 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2943); return
NS_ERROR_FAILURE; } } while (false)
;
2944
2945#ifdef XP_MACOSX
2946 InitializeMacApp();
2947#endif
2948
2949 { // extra scoping is needed so we release these components before xpcom
2950 // shutdown
2951 nsCOMPtr<nsIStringBundleService> sbs =
2952 mozilla::components::StringBundle::Service();
2953 NS_ENSURE_TRUE(sbs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sbs)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sbs" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2953); return NS_ERROR_FAILURE; } } while (false)
;
2954
2955 nsCOMPtr<nsIStringBundle> sb;
2956 sbs->CreateBundle(kProfileProperties, getter_AddRefs(sb));
2957 NS_ENSURE_TRUE_LOG(sbs, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(sbs)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "sbs" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2957); gLogConsoleErrors = true; return NS_ERROR_FAILURE; }
} while (0)
;
2958
2959 NS_ConvertUTF8toUTF16 appName(gAppData->name);
2960 AutoTArray<nsString, 3> params = {appName, appName, appName};
2961
2962 nsAutoString killMessage;
2963#ifndef XP_MACOSX
2964 rv = sb->FormatStringFromName(
2965 aUnlocker ? "restartMessageUnlocker" : "restartMessageNoUnlocker2",
2966 params, killMessage);
2967#else
2968 rv = sb->FormatStringFromName(
2969 aUnlocker ? "restartMessageUnlockerMac" : "restartMessageNoUnlockerMac",
2970 params, killMessage);
2971#endif
2972 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2972); return
NS_ERROR_FAILURE; } } while (false)
;
2973
2974 params.SetLength(1);
2975 nsAutoString killTitle;
2976 rv = sb->FormatStringFromName("restartTitle", params, killTitle);
2977 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 2977); return
NS_ERROR_FAILURE; } } while (false)
;
2978
2979#ifdef MOZ_BACKGROUNDTASKS1
2980 if (BackgroundTasks::IsBackgroundTaskMode()) {
2981 // This error is handled specially to exit with a non-zero exit code.
2982 printf_stderr("%s\n", NS_LossyConvertUTF16toASCII(killMessage).get());
2983 return NS_ERROR_UNEXPECTED;
2984 }
2985#endif
2986
2987 if (gfxPlatform::IsHeadless()) {
2988 // TODO: make a way to turn off all dialogs when headless.
2989 Output(true, "%s\n", NS_LossyConvertUTF16toASCII(killMessage).get());
2990 return NS_ERROR_FAILURE;
2991 }
2992
2993 nsCOMPtr<nsIPromptService> ps(do_GetService(NS_PROMPTSERVICE_CONTRACTID"@mozilla.org/prompter;1"));
2994 NS_ENSURE_TRUE(ps, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(ps)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "ps" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 2994); return NS_ERROR_FAILURE; } } while (false)
;
2995
2996 if (aUnlocker) {
2997 int32_t button;
2998#ifdef MOZ_WIDGET_ANDROID
2999 // On Android we always kill the process if the lock is still being held
3000 button = 0;
3001#else
3002 const uint32_t flags = (nsIPromptService::BUTTON_TITLE_IS_STRING *
3003 nsIPromptService::BUTTON_POS_0) +
3004 (nsIPromptService::BUTTON_TITLE_CANCEL *
3005 nsIPromptService::BUTTON_POS_1);
3006
3007 bool checkState = false;
3008 rv = ps->ConfirmEx(nullptr, killTitle.get(), killMessage.get(), flags,
3009 killTitle.get(), nullptr, nullptr, nullptr,
3010 &checkState, &button);
3011 NS_ENSURE_SUCCESS_LOG(rv, rv)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3011); gLogConsoleErrors = true; return rv; } } while (0)
;
3012#endif
3013
3014 if (button == 0) {
3015 rv = aUnlocker->Unlock(nsIProfileUnlocker::FORCE_QUIT);
3016 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3017 return rv;
3018 }
3019
3020 SaveFileToEnv("XRE_PROFILE_PATH", aProfileDir);
3021 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", aProfileLocalDir);
3022
3023 return LaunchChild(false, true);
3024 }
3025 } else {
3026 rv = ps->Alert(nullptr, killTitle.get(), killMessage.get());
3027 NS_ENSURE_SUCCESS_LOG(rv, rv)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3027); gLogConsoleErrors = true; return rv; } } while (0)
;
3028 }
3029
3030 return NS_ERROR_ABORT;
3031 }
3032}
3033
3034MOZ_CAN_RUN_SCRIPT
3035static ReturnAbortOnError ShowProfileDialog(
3036 nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative,
3037 const char* aDialogURL, const char* aTelemetryEnvVar) {
3038 nsresult rv;
3039
3040 nsCOMPtr<nsIFile> profD, profLD;
3041 bool offline = false;
3042 int32_t dialogReturn;
3043
3044 // We aren't going to start this instance so we can unblock other instances
3045 // from starting up.
3046#if defined(MOZ_HAS_REMOTE1)
3047 gStartupLock = nullptr;
3048#endif
3049
3050 {
3051 ScopedXPCOMStartup xpcom;
3052 rv = xpcom.Initialize();
3053 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3053); return rv; } } while (false)
;
3054
3055 rv = xpcom.SetWindowCreator(aNative);
3056 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3056); return
NS_ERROR_FAILURE; } } while (false)
;
3057
3058#ifdef XP_MACOSX
3059 InitializeMacApp();
3060 CommandLineServiceMac::SetupMacCommandLine(gRestartArgc, gRestartArgv,
3061 true);
3062#endif
3063
3064 { // extra scoping is needed so we release these components before xpcom
3065 // shutdown
3066 nsCOMPtr<nsIWindowWatcher> windowWatcher(
3067 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1"));
3068 nsCOMPtr<nsIDialogParamBlock> ioParamBlock(
3069 do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID"@mozilla.org/embedcomp/dialogparam;1"));
3070 nsCOMPtr<nsIMutableArray> dlgArray(
3071 do_CreateInstance(NS_ARRAY_CONTRACTID"@mozilla.org/array;1"));
3072 NS_ENSURE_TRUE(windowWatcher && ioParamBlock && dlgArray,do { if ((__builtin_expect(!!(!(windowWatcher && ioParamBlock
&& dlgArray)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "windowWatcher && ioParamBlock && dlgArray"
") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3073); return NS_ERROR_FAILURE; } } while (false)
3073 NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(windowWatcher && ioParamBlock
&& dlgArray)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "windowWatcher && ioParamBlock && dlgArray"
") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3073); return NS_ERROR_FAILURE; } } while (false)
;
3074
3075 ioParamBlock->SetObjects(dlgArray);
3076
3077 nsCOMPtr<nsIAppStartup> appStartup(components::AppStartup::Service());
3078 NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(appStartup)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "appStartup" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3078
); return NS_ERROR_FAILURE; } } while (false)
;
3079
3080 nsAutoCString features("centerscreen,chrome,modal,titlebar");
3081 // If we're launching a private browsing window make sure to set that
3082 // feature for the Profile Manager window as well, so it groups correctly
3083 // on the Windows taskbar.
3084 if (CheckArgExists("private-window") == ARG_FOUND) {
3085 features.AppendLiteral(",private");
3086 }
3087 nsCOMPtr<mozIDOMWindowProxy> newWindow;
3088 rv = windowWatcher->OpenWindow(nullptr, nsDependentCString(aDialogURL),
3089 u"_blank"_ns, features, ioParamBlock,
3090 getter_AddRefs(newWindow));
3091
3092 NS_ENSURE_SUCCESS_LOG(rv, rv)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3092); gLogConsoleErrors = true; return rv; } } while (0)
;
3093
3094 rv = ioParamBlock->GetInt(0, &dialogReturn);
3095 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || dialogReturn == nsIToolkitProfileService::exit) {
3096 return NS_ERROR_ABORT;
3097 }
3098
3099 int32_t startOffline;
3100 rv = ioParamBlock->GetInt(1, &startOffline);
3101 offline = NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && startOffline == 1;
3102
3103 rv = dlgArray->QueryElementAt(0, NS_GET_IID(nsIFile)(nsIFile::kIID),
3104 getter_AddRefs(profD));
3105 NS_ENSURE_SUCCESS_LOG(rv, rv)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3105); gLogConsoleErrors = true; return rv; } } while (0)
;
3106
3107 rv = dlgArray->QueryElementAt(1, NS_GET_IID(nsIFile)(nsIFile::kIID),
3108 getter_AddRefs(profLD));
3109 NS_ENSURE_SUCCESS_LOG(rv, rv)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3109); gLogConsoleErrors = true; return rv; } } while (0)
;
3110
3111 if (dialogReturn == nsIToolkitProfileService::launchWithProfile) {
3112 int32_t newArguments;
3113 rv = ioParamBlock->GetInt(2, &newArguments);
3114
3115 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && newArguments > 0) {
3116 char** newArgv = (char**)realloc(
3117 gRestartArgv, sizeof(char*) * (gRestartArgc + newArguments + 1));
3118 NS_ENSURE_TRUE(newArgv, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(newArgv)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "newArgv" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3118); return
NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
3119
3120 gRestartArgv = newArgv;
3121
3122 for (auto i = 0; i < newArguments; i++) {
3123 char16_t* arg;
3124 ioParamBlock->GetString(i, &arg);
3125 gRestartArgv[gRestartArgc++] =
3126 strdup(NS_ConvertUTF16toUTF8(nsDependentString(arg)).get());
3127 }
3128
3129 gRestartArgv[gRestartArgc] = nullptr;
3130 }
3131 }
3132 }
3133 }
3134
3135 if (offline) {
3136 SaveToEnv("XRE_START_OFFLINE=1");
3137 }
3138
3139 // User requested that we restart back into the profile manager.
3140 if (dialogReturn == nsIToolkitProfileService::restart) {
3141 SaveToEnv("XRE_RESTART_TO_PROFILE_MANAGER=1");
3142 } else {
3143 MOZ_ASSERT(dialogReturn == nsIToolkitProfileService::launchWithProfile)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(dialogReturn == nsIToolkitProfileService::launchWithProfile
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(dialogReturn == nsIToolkitProfileService::launchWithProfile
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"dialogReturn == nsIToolkitProfileService::launchWithProfile"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3143); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "dialogReturn == nsIToolkitProfileService::launchWithProfile"
")"); do { MOZ_CrashSequence(__null, 3143); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3144 SaveFileToEnv("XRE_PROFILE_PATH", profD);
3145 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
3146 }
3147 SaveToEnv(aTelemetryEnvVar);
3148
3149 if (gRestartedByOS) {
3150 // Re-add this argument when actually starting the application.
3151 char** newArgv =
3152 (char**)realloc(gRestartArgv, sizeof(char*) * (gRestartArgc + 2));
3153 NS_ENSURE_TRUE(newArgv, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(newArgv)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "newArgv" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3153); return
NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
3154 gRestartArgv = newArgv;
3155 gRestartArgv[gRestartArgc++] = const_cast<char*>("-os-restarted");
3156 gRestartArgv[gRestartArgc] = nullptr;
3157 }
3158
3159 return LaunchChild(false, true);
3160}
3161
3162MOZ_CAN_RUN_SCRIPT
3163static ReturnAbortOnError ShowProfileManager(
3164 nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative) {
3165 static const char kProfileManagerURL[] =
3166 "chrome://mozapps/content/profile/profileSelection.xhtml";
3167 static const char kTelemetryEnv[] = "XRE_RESTARTED_BY_PROFILE_MANAGER=1";
3168
3169 return ShowProfileDialog(aProfileSvc, aNative, kProfileManagerURL,
3170 kTelemetryEnv);
3171}
3172
3173MOZ_CAN_RUN_SCRIPT
3174static ReturnAbortOnError ShowProfileSelector(
3175 nsIToolkitProfileService* aProfileSvc, nsINativeAppSupport* aNative) {
3176 static const char kProfileSelectorURL[] = "about:profilemanager";
3177 static const char kTelemetryEnv[] = "XRE_RESTARTED_BY_PROFILE_SELECTOR=1";
3178
3179 return ShowProfileDialog(aProfileSvc, aNative, kProfileSelectorURL,
3180 kTelemetryEnv);
3181}
3182
3183// Both profile dialogs relaunch Firefox to start the chosen profile, and macOS
3184// hands an ASWebAuthenticationSession request to the process it launched rather
3185// than to the relaunched one, so showing a dialog would drop the request.
3186static bool ShouldSkipProfileDialogForWebAuth() {
3187#if defined(XP_MACOSX)
3188 return WasLaunchedByAuthenticationServices();
3189#else
3190 return false;
3191#endif
3192}
3193
3194static bool gDoMigration = false;
3195static bool gDoProfileReset = false;
3196constinit static nsCOMPtr<nsIToolkitProfile> gResetOldProfile;
3197
3198static nsresult LockProfile(nsINativeAppSupport* aNative, nsIFile* aRootDir,
3199 nsIFile* aLocalDir, nsIToolkitProfile* aProfile,
3200 nsIProfileLock** aResult) {
3201 // If you close Firefox and very quickly reopen it, the old Firefox may
3202 // still be closing down. Rather than immediately showing the
3203 // "Firefox is running but is not responding" message, we spend a few
3204 // seconds retrying first.
3205
3206 static const int kLockRetrySeconds = 5;
3207 static const int kLockRetrySleepMS = 100;
3208
3209 nsresult rv;
3210 nsCOMPtr<nsIProfileUnlocker> unlocker;
3211 const TimeStamp start = TimeStamp::Now();
3212 do {
3213 if (aProfile) {
3214 rv = aProfile->Lock(getter_AddRefs(unlocker), aResult);
3215 } else {
3216 rv = NS_LockProfilePath(aRootDir, aLocalDir, getter_AddRefs(unlocker),
3217 aResult);
3218 }
3219 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3220 StartupTimeline::Record(StartupTimeline::AFTER_PROFILE_LOCKED);
3221 return NS_OK;
3222 }
3223 PR_Sleep(kLockRetrySleepMS);
3224 } while (TimeStamp::Now() - start <
3225 TimeDuration::FromSeconds(kLockRetrySeconds));
3226
3227 return ProfileLockedDialog(aRootDir, aLocalDir, unlocker, aNative, aResult);
3228}
3229
3230// Pick a profile. We need to end up with a profile root dir, local dir and
3231// potentially an nsIToolkitProfile instance.
3232//
3233// 1) check for --profile <path>
3234// 2) check for -P <name>
3235// 3) check for --ProfileManager
3236// 4) use the default profile, if there is one
3237// 5) if there are *no* profiles, set up profile-migration
3238// 6) display the profile-manager UI
3239MOZ_CAN_RUN_SCRIPT
3240static nsresult SelectProfile(nsToolkitProfileService* aProfileSvc,
3241 nsINativeAppSupport* aNative, nsIFile** aRootDir,
3242 nsIFile** aLocalDir, nsIToolkitProfile** aProfile,
3243 bool* aWasDefaultSelection) {
3244 StartupTimeline::Record(StartupTimeline::SELECT_PROFILE);
3245
3246 nsresult rv;
3247
3248 if (EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
3249 gDoProfileReset = true;
3250 gDoMigration = true;
3251 }
3252
3253 // reset-profile and migration args need to be checked before any profiles are
3254 // chosen below.
3255 ArgResult ar = CheckArg("reset-profile");
3256 if (ar == ARG_FOUND) {
3257 gDoProfileReset = true;
3258 }
3259
3260 ar = CheckArg("migration");
3261 if (ar == ARG_FOUND) {
3262 gDoMigration = true;
3263 }
3264
3265#if defined(XP_WIN)
3266 // This arg is only used to indicate to telemetry that a profile refresh
3267 // (reset+migration) was requested from the uninstaller, pass this along
3268 // via an environment variable for simplicity.
3269 ar = CheckArg("uninstaller-profile-refresh");
3270 if (ar == ARG_FOUND) {
3271 SaveToEnv("MOZ_UNINSTALLER_PROFILE_REFRESH=1");
3272 }
3273#endif
3274
3275 if (EnvHasValue("XRE_RESTART_TO_PROFILE_MANAGER")) {
3276 return ShowProfileManager(aProfileSvc, aNative);
3277 }
3278
3279 // Ask the profile manager to select the profile directories to use.
3280 bool didCreate = false;
3281 rv = aProfileSvc->SelectStartupProfile(&gArgc, gArgv, gDoProfileReset,
3282 aRootDir, aLocalDir, aProfile,
3283 &didCreate, aWasDefaultSelection);
3284
3285 if (rv == NS_ERROR_SHOW_PROFILE_MANAGER) {
3286 return ShowProfileManager(aProfileSvc, aNative);
3287 }
3288
3289 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3289); return rv; } } while (false)
;
3290
3291 if (didCreate) {
3292 // For a fresh install, we would like to let users decide
3293 // to do profile migration on their own later after using.
3294 gDoProfileReset = false;
3295 gDoMigration = false;
3296 }
3297
3298 if (gDoProfileReset && !*aProfile) {
3299 NS_WARNING("Profile reset is only supported for named profiles.")NS_DebugBreak(NS_DEBUG_WARNING, "Profile reset is only supported for named profiles."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3299)
;
3300 return NS_ERROR_ABORT;
3301 }
3302
3303 // Block reset without migration for selectable profiles.
3304 // Bug 2020801: Update this to allow resetting without migration
3305 if (gDoProfileReset && !gDoMigration && *aProfile) {
3306 nsCString storeID;
3307 (*aProfile)->GetStoreID(storeID);
3308 if (!storeID.IsVoid()) {
3309 NS_WARNING("Selectable profiles cannot be reset without migration.")NS_DebugBreak(NS_DEBUG_WARNING, "Selectable profiles cannot be reset without migration."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3309)
;
3310 return NS_ERROR_ABORT;
3311 }
3312 }
3313
3314 // No profile could be found. This generally shouldn't happen, a new profile
3315 // should be created in all cases except for profile reset which is covered
3316 // above, but just in case...
3317 if (!*aRootDir) {
3318 NS_WARNING("Failed to select or create profile.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to select or create profile."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3318)
;
3319 return NS_ERROR_ABORT;
3320 }
3321
3322 return NS_OK;
3323}
3324
3325#ifdef MOZ_BLOCK_PROFILE_DOWNGRADE1
3326struct FileWriteFunc final : public JSONWriteFunc {
3327 FILE* mFile;
3328 explicit FileWriteFunc(FILE* aFile) : mFile(aFile) {}
3329
3330 void Write(const Span<const char>& aStr) final {
3331 fprintf(mFile, "%.*s", int(aStr.size()), aStr.data());
3332 }
3333};
3334
3335// Parses a JSON string and returns the raw install_timestamp value, or
3336// Nothing() if the JSON is malformed or lacks the property.
3337static mozilla::Maybe<uint64_t> ParseInstallTimestamp(
3338 std::string_view aUtf8Json) {
3339 Json::Value root;
3340 Json::Reader reader;
3341 if (!reader.parse(aUtf8Json.data(), aUtf8Json.data() + aUtf8Json.size(),
3342 root) ||
3343 !root.isMember("install_timestamp")) {
3344 return mozilla::Nothing();
3345 }
3346
3347 std::string tsStr = root["install_timestamp"].asString();
3348 char* end = nullptr;
3349 uint64_t val = strtoull(tsStr.c_str(), &end, 10);
3350 if (!end || *end != '\0') {
3351 return mozilla::Nothing();
3352 }
3353 return mozilla::Some(val);
3354}
3355
3356# ifndef XP_MACOSX
3357// Reads aJsonFile and returns the raw install_timestamp value, or Nothing() if
3358// the file is absent, unreadable, or lacks the property.
3359static mozilla::Maybe<uint64_t> ReadInstallTimestamp(nsIFile* aJsonFile,
3360 bool aIsUTF16LE) {
3361 FILE* raw = nullptr;
3362 if (NS_FAILED(aJsonFile->OpenANSIFileDesc("rb", &raw))((bool)(__builtin_expect(!!(NS_FAILED_impl(aJsonFile->OpenANSIFileDesc
("rb", &raw))), 0)))
|| !raw) {
1
Assuming the condition is true
2
Assuming 'raw' is non-null
3
Taking false branch
3363 return mozilla::Nothing();
3364 }
3365 ScopedCloseFile f(raw);
3366
3367 fseek(f.get(), 0, SEEK_END2);
3368 auto len = ftell(f.get());
3369 if (len <= 0) {
4
Assuming 'len' is > 0
5
Taking false branch
3370 return mozilla::Nothing();
3371 }
3372 rewind(f.get());
6
After calling 'rewind' reading 'errno' is required to find out if the call has failed
3373
3374 auto buf = MakeUnique<uint8_t[]>(len);
7
Calling 'MakeUnique<unsigned char[], long &>'
3375 if (fread(buf.get(), 1, len, f.get()) != (size_t)len) {
3376 return mozilla::Nothing();
3377 }
3378
3379 nsAutoCString converted;
3380 std::string_view utf8View;
3381 if (aIsUTF16LE) {
3382# if __BYTE_ORDER__1234 == __ORDER_LITTLE_ENDIAN__1234
3383 const char16_t* chars = reinterpret_cast<const char16_t*>(buf.get());
3384 uint32_t charLen = len / 2;
3385 CopyUTF16toUTF8(Span(chars, charLen), converted);
3386 utf8View = std::string_view(converted.get(), converted.Length());
3387# else
3388 MOZ_ASSERT_UNREACHABLE(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"UTF-16LE reading not supported on big-endian architectures"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3389
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"UTF-16LE reading not supported on big-endian architectures"
")"); do { MOZ_CrashSequence(__null, 3389); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3389 "UTF-16LE reading not supported on big-endian architectures")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"UTF-16LE reading not supported on big-endian architectures"
")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3389
); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") (" "MOZ_ASSERT_UNREACHABLE: "
"UTF-16LE reading not supported on big-endian architectures"
")"); do { MOZ_CrashSequence(__null, 3389); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3390 return mozilla::Nothing();
3391# endif
3392 } else {
3393 utf8View = std::string_view(reinterpret_cast<const char*>(buf.get()), len);
3394 }
3395
3396 return ParseInstallTimestamp(utf8View);
3397}
3398# endif // !XP_MACOSX
3399
3400Maybe<mozilla::PathString> GenerateDowngradeTelemetry(
3401 const nsACString& aPingId, const nsCString& aLastVersion, bool aHasSync,
3402 int32_t aButton, const nsACString& aChannel,
3403 const nsACString& aProfileSelectionReason,
3404 mozilla::Maybe<PRTime> aReplacedLockTime, bool aIsDifferentInstall) {
3405 nsCOMPtr<nsIPrefService> prefSvc =
3406 do_GetService("@mozilla.org/preferences-service;1");
3407 NS_ENSURE_TRUE(prefSvc, Nothing())do { if ((__builtin_expect(!!(!(prefSvc)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefSvc" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3407); return
Nothing(); } } while (false)
;
3408
3409 nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(prefSvc);
3410 NS_ENSURE_TRUE(prefBranch, Nothing())do { if ((__builtin_expect(!!(!(prefBranch)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefBranch" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3410
); return Nothing(); } } while (false)
;
3411
3412 nsCString clientId;
3413 nsresult rv =
3414 prefBranch->GetCharPref("toolkit.telemetry.cachedClientID", clientId);
3415 NS_ENSURE_SUCCESS(rv, Nothing())do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "Nothing()", static_cast<
uint32_t>(__rv), name ? " (" : "", name ? name : "", name ?
")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3415); return
Nothing(); } } while (false)
;
3416
3417 nsCString profileGroupId;
3418 rv = prefBranch->GetCharPref("toolkit.telemetry.cachedProfileGroupID",
3419 profileGroupId);
3420 NS_ENSURE_SUCCESS(rv, Nothing())do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "Nothing()", static_cast<
uint32_t>(__rv), name ? " (" : "", name ? name : "", name ?
")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3420); return
Nothing(); } } while (false)
;
3421
3422 nsCString arch("null");
3423 nsCOMPtr<nsIPropertyBag2> sysInfo =
3424 do_GetService("@mozilla.org/system-info;1");
3425 NS_ENSURE_TRUE(sysInfo, Nothing())do { if ((__builtin_expect(!!(!(sysInfo)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "sysInfo" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3425); return
Nothing(); } } while (false)
;
3426 sysInfo->GetPropertyAsACString(u"arch"_ns, arch);
3427
3428 bool isMSIX = false;
3429# ifdef XP_WIN
3430 rv = sysInfo->GetPropertyAsBool(u"hasWinPackageId"_ns, &isMSIX);
3431 if (rv != NS_OK) {
3432 // Don't early return.
3433 NS_ERROR("Failed to get property: hasWinPackageId")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to get property: hasWinPackageId"
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3433); MOZ_PretendNoReturn(); } while (0)
;
3434 }
3435# endif
3436
3437 mozilla::Maybe<PRTime> maybeInstallTime;
3438 mozilla::Maybe<PRTime> maybeUpdateTime;
3439 nsCOMPtr<nsIFile> greDir;
3440 if (NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_GetSpecialDirectory
("GreD", getter_AddRefs(greDir)))), 1)))
3441 NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(greDir)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(NS_GetSpecialDirectory
("GreD", getter_AddRefs(greDir)))), 1)))
) {
3442# ifdef XP_WIN
3443 // installation_telemetry.json uses a Windows FILETIME (100ns intervals
3444 // since Jan 1, 1601 UTC).
3445 nsCOMPtr<nsIFile> installTelemetry;
3446 if (NS_SUCCEEDED(greDir->Clone(getter_AddRefs(installTelemetry)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(greDir->Clone(
getter_AddRefs(installTelemetry)))), 1)))
&&
3447 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(installTelemetry->
Append(u"installation_telemetry.json"_ns))), 1)))
3448 installTelemetry->Append(u"installation_telemetry.json"_ns))((bool)(__builtin_expect(!!(!NS_FAILED_impl(installTelemetry->
Append(u"installation_telemetry.json"_ns))), 1)))
) {
3449 if (auto filetime =
3450 ReadInstallTimestamp(installTelemetry, /* aIsUTF16LE */ true)) {
3451 constexpr uint64_t kEpochOffset = 116444736000000000ULL;
3452 if (*filetime > kEpochOffset) {
3453 // The offset converts to an epoch of 1970, divide by 10 to convert
3454 // from 100ns to usec
3455 maybeInstallTime =
3456 mozilla::Some(PRTime((*filetime - kEpochOffset) / 10));
3457 }
3458 }
3459 }
3460# endif
3461
3462# ifdef XP_MACOSX
3463 // GreD is <app>.app/Contents/Resources; go up two levels to the .app
3464 // bundle directory where the updater stores the xattr.
3465 maybeUpdateTime = [&]() -> mozilla::Maybe<PRTime> {
3466 nsCOMPtr<nsIFile> contentsDir;
3467 if (NS_FAILED(greDir->GetParent(getter_AddRefs(contentsDir)))((bool)(__builtin_expect(!!(NS_FAILED_impl(greDir->GetParent
(getter_AddRefs(contentsDir)))), 0)))
||
3468 !contentsDir) {
3469 return mozilla::Nothing();
3470 }
3471 nsCOMPtr<nsIFile> appBundle;
3472 if (NS_FAILED(contentsDir->GetParent(getter_AddRefs(appBundle)))((bool)(__builtin_expect(!!(NS_FAILED_impl(contentsDir->GetParent
(getter_AddRefs(appBundle)))), 0)))
||
3473 !appBundle) {
3474 return mozilla::Nothing();
3475 }
3476 nsCOMPtr<nsILocalFileMac> macFile = do_QueryInterface(appBundle);
3477 if (!macFile) {
3478 return mozilla::Nothing();
3479 }
3480 nsTArray<uint8_t> attrValue;
3481 if (NS_FAILED(macFile->GetXAttr("org.mozilla.update-telemetry"_ns,((bool)(__builtin_expect(!!(NS_FAILED_impl(macFile->GetXAttr
("org.mozilla.update-telemetry"_ns, attrValue))), 0)))
3482 attrValue))((bool)(__builtin_expect(!!(NS_FAILED_impl(macFile->GetXAttr
("org.mozilla.update-telemetry"_ns, attrValue))), 0)))
) {
3483 return mozilla::Nothing();
3484 }
3485 auto msTime = ParseInstallTimestamp(
3486 std::string_view(reinterpret_cast<const char*>(attrValue.Elements()),
3487 attrValue.Length()));
3488 if (!msTime) {
3489 return mozilla::Nothing();
3490 }
3491 return mozilla::Some(PRTime(int64_t(*msTime) * PR_USEC_PER_MSEC1000L));
3492 }();
3493# else
3494 // update_telemetry.json uses a Unix timestamp in milliseconds.
3495 nsCOMPtr<nsIFile> updateTelemetry;
3496 if (NS_SUCCEEDED(greDir->Clone(getter_AddRefs(updateTelemetry)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(greDir->Clone(
getter_AddRefs(updateTelemetry)))), 1)))
&&
3497 NS_SUCCEEDED(updateTelemetry->Append(u"update_telemetry.json"_ns))((bool)(__builtin_expect(!!(!NS_FAILED_impl(updateTelemetry->
Append(u"update_telemetry.json"_ns))), 1)))
) {
3498 if (auto msTime =
3499 ReadInstallTimestamp(updateTelemetry, /* aIsUTF16LE */ false)) {
3500 maybeUpdateTime =
3501 mozilla::Some(PRTime(int64_t(*msTime) * PR_USEC_PER_MSEC1000L));
3502 }
3503 }
3504# endif
3505 }
3506
3507 PRTime nowUsec = PR_Now();
3508 time_t nowTime = time_t(nowUsec / PR_USEC_PER_SEC1000000L);
3509 char date[sizeof "YYYY-MM-DDThh:mm:ss.000Z"];
3510 strftime(date, sizeof date, "%FT%T.000Z", gmtime(&nowTime));
3511
3512 constexpr auto pingType = "downgrade"_ns;
3513
3514 int32_t pos = aLastVersion.Find("_");
3515 if (pos == kNotFound) {
3516 return Nothing();
3517 }
3518
3519 const nsDependentCSubstring lastVersion = Substring(aLastVersion, 0, pos);
3520 const nsDependentCSubstring lastBuildId =
3521 Substring(aLastVersion, pos + 1, 14);
3522
3523 nsCOMPtr<nsIFile> pingFile;
3524 rv = NS_GetSpecialDirectory(XRE_USER_APP_DATA_DIR"UAppData", getter_AddRefs(pingFile));
3525 NS_ENSURE_SUCCESS(rv, Nothing())do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "Nothing()", static_cast<
uint32_t>(__rv), name ? " (" : "", name ? name : "", name ?
")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3525); return
Nothing(); } } while (false)
;
3526 rv = pingFile->Append(u"Pending Pings"_ns);
3527 NS_ENSURE_SUCCESS(rv, Nothing())do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "Nothing()", static_cast<
uint32_t>(__rv), name ? " (" : "", name ? name : "", name ?
")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3527); return
Nothing(); } } while (false)
;
3528 rv = pingFile->Create(nsIFile::DIRECTORY_TYPE, 0755);
3529 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) && rv != NS_ERROR_FILE_ALREADY_EXISTS) {
3530 return Nothing();
3531 }
3532 rv = pingFile->Append(NS_ConvertUTF8toUTF16(aPingId));
3533 NS_ENSURE_SUCCESS(rv, Nothing())do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "Nothing()", static_cast<
uint32_t>(__rv), name ? " (" : "", name ? name : "", name ?
")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3533); return
Nothing(); } } while (false)
;
3534
3535 FILE* file;
3536 rv = pingFile->OpenANSIFileDesc("w", &file);
3537 NS_ENSURE_SUCCESS(rv, Nothing())do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "Nothing()", static_cast<
uint32_t>(__rv), name ? " (" : "", name ? name : "", name ?
")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3537); return
Nothing(); } } while (false)
;
3538
3539 JSONWriter w(MakeUnique<FileWriteFunc>(file));
3540 w.Start();
3541 {
3542 w.StringProperty("type",
3543 Span<const char>(pingType.Data(), pingType.Length()));
3544 w.StringProperty("id", PromiseFlatCStringTPromiseFlatString<char>(aPingId));
3545 w.StringProperty("creationDate", MakeStringSpan(date));
3546 w.IntProperty("version", TELEMETRY_PING_FORMAT_VERSION4);
3547 w.StringProperty("clientId", clientId);
3548 w.StringProperty("profileGroupId", profileGroupId);
3549 w.StartObjectProperty("application");
3550 {
3551 w.StringProperty("architecture", arch);
3552 w.StringProperty(
3553 "buildId",
3554 MakeStringSpan(static_cast<const char*>(gAppData->buildID)));
3555 w.StringProperty(
3556 "name", MakeStringSpan(static_cast<const char*>(gAppData->name)));
3557 w.StringProperty(
3558 "version",
3559 MakeStringSpan(static_cast<const char*>(gAppData->version)));
3560 w.StringProperty("displayVersion",
3561 MOZ_STRINGIFY(MOZ_APP_VERSION_DISPLAY)"160.0a1");
3562 w.StringProperty(
3563 "vendor", MakeStringSpan(static_cast<const char*>(gAppData->vendor)));
3564 w.StringProperty("platformVersion", gToolkitVersion);
3565# ifdef TARGET_XPCOM_ABI"x86_64-gcc3"
3566 w.StringProperty("xpcomAbi", TARGET_XPCOM_ABI"x86_64-gcc3");
3567# else
3568 w.StringProperty("xpcomAbi", "unknown");
3569# endif
3570 w.StringProperty("channel", PromiseFlatCStringTPromiseFlatString<char>(aChannel));
3571 }
3572 w.EndObject();
3573 w.StartObjectProperty("payload");
3574 {
3575 w.StringProperty("lastVersion", PromiseFlatCStringTPromiseFlatString<char>(lastVersion));
3576 w.StringProperty("lastBuildId", PromiseFlatCStringTPromiseFlatString<char>(lastBuildId));
3577 w.BoolProperty("hasSync", aHasSync);
3578 w.IntProperty("button", aButton);
3579 w.BoolProperty("isMSIX", isMSIX);
3580 w.StringProperty("profileSelectionReason",
3581 PromiseFlatCStringTPromiseFlatString<char>(aProfileSelectionReason));
3582
3583 w.BoolProperty("isDifferentInstall", aIsDifferentInstall);
3584
3585 if (aReplacedLockTime) {
3586 // aReplacedLockTime is in milliseconds.
3587 PRTime lockTimeUsec = *aReplacedLockTime * PR_USEC_PER_MSEC1000L;
3588 constexpr int64_t kUsecsPerDay =
3589 int64_t(PR_USEC_PER_SEC1000000L) * 60 * 60 * 24;
3590 int64_t elapsedUsec = nowUsec - lockTimeUsec;
3591 if (elapsedUsec >= 0) {
3592 w.IntProperty("daysSinceLock", elapsedUsec / kUsecsPerDay);
3593 }
3594 if (maybeInstallTime) {
3595 w.BoolProperty("isNewInstall", *maybeInstallTime > lockTimeUsec);
3596 }
3597 if (maybeUpdateTime) {
3598 w.BoolProperty("isNewUpdate", *maybeUpdateTime > lockTimeUsec);
3599 }
3600 }
3601 }
3602 w.EndObject();
3603 }
3604 w.End();
3605
3606 fclose(file);
3607 return Some(pingFile->NativePath());
3608}
3609
3610bool BuildDowngradePingUrl(const nsACString& aPingId,
3611 const nsACString& aChannel, nsACString& aUrlOut) {
3612 nsCOMPtr<nsIPrefService> prefSvc =
3613 do_GetService("@mozilla.org/preferences-service;1");
3614 NS_ENSURE_TRUE(prefSvc, false)do { if ((__builtin_expect(!!(!(prefSvc)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefSvc" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3614); return
false; } } while (false)
;
3615
3616 nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(prefSvc);
3617 NS_ENSURE_TRUE(prefBranch, false)do { if ((__builtin_expect(!!(!(prefBranch)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefBranch" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3617
); return false; } } while (false)
;
3618
3619 nsCString server;
3620 nsresult rv = prefBranch->GetCharPref("toolkit.telemetry.server", server);
3621 NS_ENSURE_SUCCESS(rv, false)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "false", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3621); return false; } } while (false)
;
3622
3623 aUrlOut = nsPrintfCString(
3624 "%s/submit/telemetry/%s/%s/%s/%s/%s/%s?v=%d", server.get(),
3625 PromiseFlatCStringTPromiseFlatString<char>(aPingId).get(), "downgrade",
3626 (const char*)gAppData->name, (const char*)gAppData->version,
3627 PromiseFlatCStringTPromiseFlatString<char>(aChannel).get(), (const char*)gAppData->buildID,
3628 TELEMETRY_PING_FORMAT_VERSION4);
3629 return true;
3630}
3631
3632static void SubmitDowngradeTelemetry(const nsACString& aProfileSelectionReason,
3633 mozilla::Maybe<PRTime> aReplacedLockTime,
3634 const nsCString& aLastVersion,
3635 bool aHasSync, int32_t aButton,
3636 bool aIsDifferentInstall) {
3637 nsCOMPtr<nsIPrefService> prefSvc =
3638 do_GetService("@mozilla.org/preferences-service;1");
3639 NS_ENSURE_TRUE_VOID(prefSvc)do { if ((__builtin_expect(!!(!(prefSvc)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefSvc" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3639); return
; } } while (false)
;
3640
3641 nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(prefSvc);
3642 NS_ENSURE_TRUE_VOID(prefBranch)do { if ((__builtin_expect(!!(!(prefBranch)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefBranch" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3642
); return; } } while (false)
;
3643
3644 bool enabled;
3645 nsresult rv =
3646 prefBranch->GetBoolPref(kPrefHealthReportUploadEnabled, &enabled);
3647 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3647); return; } } while (false)
;
3648 if (!enabled) {
3649 return;
3650 }
3651
3652 nsCOMPtr<nsIFile> pingSender;
3653 rv = NS_GetSpecialDirectory(NS_GRE_BIN_DIR"GreBinD", getter_AddRefs(pingSender));
3654 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3654); return; } } while (false)
;
3655# ifdef XP_WIN
3656 pingSender->Append(u"pingsender.exe"_ns);
3657# else
3658 pingSender->Append(u"pingsender"_ns);
3659# endif
3660
3661 bool exists;
3662 rv = pingSender->Exists(&exists);
3663 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3663); return; } } while (false)
;
3664 if (!exists) {
3665 return;
3666 }
3667
3668 rv = prefSvc->GetDefaultBranch(nullptr, getter_AddRefs(prefBranch));
3669 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3669); return; } } while (false)
;
3670
3671 nsCString channel("default");
3672 rv = prefBranch->GetCharPref("app.update.channel", channel);
3673 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3673); return; } } while (false)
;
3674
3675 nsID uuid;
3676 rv = nsID::GenerateUUIDInPlace(uuid);
3677 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3677); return; } } while (false)
;
3678 NSID_TrimBracketsASCII pingId(uuid);
3679
3680 nsCString url;
3681 if (!BuildDowngradePingUrl(pingId, channel, url)) {
3682 return;
3683 }
3684
3685 Maybe<PathString> filePath = GenerateDowngradeTelemetry(
3686 pingId, aLastVersion, aHasSync, aButton, channel, aProfileSelectionReason,
3687 aReplacedLockTime, aIsDifferentInstall);
3688 if (!filePath) {
3689 return;
3690 }
3691
3692 const filesystem::Path::value_type* args[2];
3693# ifdef XP_WIN
3694 nsString urlw = NS_ConvertUTF8toUTF16(url);
3695 args[0] = urlw.get();
3696# else
3697 args[0] = url.get();
3698# endif
3699 args[1] = filePath->get();
3700
3701 nsCOMPtr<nsIProcess> process =
3702 do_CreateInstance("@mozilla.org/process/util;1");
3703 NS_ENSURE_TRUE_VOID(process)do { if ((__builtin_expect(!!(!(process)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "process" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3703); return
; } } while (false)
;
3704 process->Init(pingSender);
3705 process->SetStartHidden(true);
3706 process->SetNoShell(true);
3707
3708# ifdef XP_WIN
3709 process->Runw(false, args, 2);
3710# else
3711 process->Run(false, args, 2);
3712# endif
3713}
3714
3715static const char kProfileDowngradeURL[] =
3716 "chrome://mozapps/content/profile/profileDowngrade.xhtml";
3717
3718MOZ_CAN_RUN_SCRIPT
3719static ReturnAbortOnError HandleDetectedDowngrade(
3720 nsIFile* aProfileDir, nsINativeAppSupport* aNative,
3721 nsToolkitProfileService* aProfileSvc, nsIProfileLock* aProfileLock,
3722 const nsCString& aLastVersion, bool aIsDifferentInstall) {
3723 int32_t result = 0;
3724 nsresult rv;
3725
3726 {
3727 if (gfxPlatform::IsHeadless()) {
3728 // TODO: make a way to turn off all dialogs when headless.
3729 Output(true,
3730 "This profile was last used with a newer version of this "
3731 "application. Please create a new profile.\n");
3732 return NS_ERROR_ABORT;
3733 }
3734
3735 ScopedXPCOMStartup xpcom;
3736 rv = xpcom.Initialize();
3737 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3737); return rv; } } while (false)
;
3738
3739 rv = xpcom.SetWindowCreator(aNative);
3740 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3740); return rv; } } while (false)
;
3741
3742# ifdef XP_MACOSX
3743 InitializeMacApp();
3744# endif
3745
3746 { // extra scoping is needed so we release these components before xpcom
3747 // shutdown
3748 bool hasSync = false;
3749 nsCOMPtr<nsIPrefService> prefSvc =
3750 do_GetService("@mozilla.org/preferences-service;1");
3751 NS_ENSURE_TRUE(prefSvc, rv)do { if ((__builtin_expect(!!(!(prefSvc)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "prefSvc" ") failed", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3751); return
rv; } } while (false)
;
3752
3753 nsCOMPtr<nsIFile> prefsFile;
3754 rv = aProfileDir->Clone(getter_AddRefs(prefsFile));
3755 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3755); return rv; } } while (false)
;
3756
3757 rv = prefsFile->Append(u"prefs.js"_ns);
3758 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3758); return rv; } } while (false)
;
3759
3760 rv = prefSvc->ReadUserPrefsFromFile(prefsFile);
3761 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
3762 nsCOMPtr<nsIPrefBranch> prefBranch = do_QueryInterface(prefSvc);
3763
3764 rv = prefBranch->PrefHasUserValue("services.sync.username", &hasSync);
3765 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3765); return rv; } } while (false)
;
3766 }
3767
3768 nsCOMPtr<nsIWindowWatcher> windowWatcher =
3769 do_GetService(NS_WINDOWWATCHER_CONTRACTID"@mozilla.org/embedcomp/window-watcher;1");
3770 NS_ENSURE_TRUE(windowWatcher, NS_ERROR_ABORT)do { if ((__builtin_expect(!!(!(windowWatcher)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "windowWatcher" ") failed"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3770); return NS_ERROR_ABORT; } } while (false)
;
3771
3772 nsCOMPtr<nsIAppStartup> appStartup(components::AppStartup::Service());
3773 NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(appStartup)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "appStartup" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3773
); return NS_ERROR_FAILURE; } } while (false)
;
3774
3775 nsCOMPtr<nsIDialogParamBlock> paramBlock =
3776 do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID"@mozilla.org/embedcomp/dialogparam;1");
3777 NS_ENSURE_TRUE(paramBlock, NS_ERROR_ABORT)do { if ((__builtin_expect(!!(!(paramBlock)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "paramBlock" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 3777
); return NS_ERROR_ABORT; } } while (false)
;
3778
3779 uint8_t flags = 0;
3780 if (hasSync) {
3781 flags |= nsIToolkitProfileService::hasSync;
3782 }
3783
3784 paramBlock->SetInt(0, flags);
3785
3786 nsAutoCString features("centerscreen,chrome,modal,titlebar");
3787 // If we're launching a private browsing window make sure to set that
3788 // feature for the Profile Manager window as well, so it groups correctly
3789 // on the Windows taskbar.
3790 if (CheckArgExists("private-window") == ARG_FOUND) {
3791 features.AppendLiteral(",private");
3792 }
3793 nsCOMPtr<mozIDOMWindowProxy> newWindow;
3794 rv = windowWatcher->OpenWindow(
3795 nullptr, nsDependentCString(kProfileDowngradeURL), u"_blank"_ns,
3796 features, paramBlock, getter_AddRefs(newWindow));
3797 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3797); return rv; } } while (false)
;
3798
3799 paramBlock->GetInt(1, &result);
3800
3801 PRTime replacedLockTime = 0;
3802 mozilla::Maybe<PRTime> maybeReplacedLockTime;
3803 if (NS_SUCCEEDED(aProfileLock->GetReplacedLockTime(&replacedLockTime))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aProfileLock->
GetReplacedLockTime(&replacedLockTime))), 1)))
&&
3804 replacedLockTime != 0) {
3805 maybeReplacedLockTime = mozilla::Some(replacedLockTime);
3806 }
3807 SubmitDowngradeTelemetry(aProfileSvc->ProfileSelectionReason(),
3808 maybeReplacedLockTime, aLastVersion, hasSync,
3809 result, aIsDifferentInstall);
3810 }
3811 }
3812
3813 if (result == nsIToolkitProfileService::createNewProfile) {
3814 // Create a new profile and start it.
3815 nsCString profileName;
3816 profileName.AssignLiteral("default");
3817# ifdef MOZ_DEDICATED_PROFILES1
3818 profileName.Append("-" MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL)"default");
3819# endif
3820 nsCOMPtr<nsIToolkitProfile> newProfile;
3821 rv = aProfileSvc->CreateUniqueProfile(nullptr, profileName, "downgrade"_ns,
3822 getter_AddRefs(newProfile));
3823 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3823); return rv; } } while (false)
;
3824 rv = aProfileSvc->SetDefaultProfile(newProfile);
3825 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3825); return rv; } } while (false)
;
3826 rv = aProfileSvc->Flush();
3827 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3827); return rv; } } while (false)
;
3828
3829 nsCOMPtr<nsIFile> profD, profLD;
3830 rv = newProfile->GetRootDir(getter_AddRefs(profD));
3831 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3831); return rv; } } while (false)
;
3832 rv = newProfile->GetLocalDir(getter_AddRefs(profLD));
3833 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 3833); return rv; } } while (false)
;
3834
3835 SaveFileToEnv("XRE_PROFILE_PATH", profD);
3836 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", profLD);
3837
3838 return LaunchChild(false, true);
3839 }
3840
3841 // Cancel
3842 return NS_ERROR_ABORT;
3843}
3844#endif
3845
3846/**
3847 * Extracts the various parts of a compatibility version string.
3848 *
3849 * Compatibility versions are of the form
3850 * "<appversion>_<appbuildid>/<platformbuildid>". The toolkit version comparator
3851 * can only handle 32-bit numbers and in the normal case build IDs are larger
3852 * than this. So if the build ID is numeric we split it into two version parts.
3853 */
3854void ExtractCompatVersionInfo(const nsACString& aCompatVersion,
3855 nsACString& aAppVersion,
3856 nsACString& aAppBuildID) {
3857 int32_t underscorePos = aCompatVersion.FindChar('_');
3858 int32_t slashPos = aCompatVersion.FindChar('/');
3859
3860 if (underscorePos == kNotFound || slashPos == kNotFound ||
3861 slashPos < underscorePos) {
3862 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "compatibility.ini Version string does not match the expected format."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3863)
3863 "compatibility.ini Version string does not match the expected format.")NS_DebugBreak(NS_DEBUG_WARNING, "compatibility.ini Version string does not match the expected format."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
3863)
;
3864
3865 // Fall back to just using the entire string as the version.
3866 aAppVersion = aCompatVersion;
3867 aAppBuildID.Truncate(0);
3868 return;
3869 }
3870
3871 aAppVersion = Substring(aCompatVersion, 0, underscorePos);
3872 aAppBuildID = Substring(aCompatVersion, underscorePos + 1,
3873 slashPos - (underscorePos + 1));
3874}
3875
3876/**
3877 * Compares the provided compatibility versions. Returns 0 if they match,
3878 * < 0 if the new version is considered an upgrade from the old version and
3879 * > 0 if the new version is considered a downgrade from the old version.
3880 */
3881int32_t CompareCompatVersions(const nsACString& aOldCompatVersion,
3882 const nsACString& aNewCompatVersion) {
3883 // Hardcode the case where the last run was in safe mode (Bug 1556612). We
3884 // cannot tell if this is a downgrade or not so just assume it isn't and let
3885 // the user proceed.
3886 if (aOldCompatVersion.EqualsLiteral("Safe Mode")) {
3887 return -1;
3888 }
3889
3890 // Extract the major version part from the version string and only use that
3891 // for version comparison.
3892 int32_t index = aOldCompatVersion.FindChar('.');
3893 const nsACString& oldMajorVersion = Substring(
3894 aOldCompatVersion, 0, index < 0 ? aOldCompatVersion.Length() : index);
3895 index = aNewCompatVersion.FindChar('.');
3896 const nsACString& newMajorVersion = Substring(
3897 aNewCompatVersion, 0, index < 0 ? aNewCompatVersion.Length() : index);
3898
3899 return CompareVersions(PromiseFlatCStringTPromiseFlatString<char>(oldMajorVersion).get(),
3900 PromiseFlatCStringTPromiseFlatString<char>(newMajorVersion).get());
3901}
3902
3903/**
3904 * Checks the compatibility.ini file to see if we have updated our application
3905 * or otherwise invalidated our caches. The result struct reports whether the
3906 * profile is compatible, whether caches are valid, whether this is a
3907 * downgrade, and the last-run version info.
3908 */
3909CompatCheckResult CheckCompatibility(nsIFile* aProfileDir,
3910 const nsCString& aVersion,
3911 const nsCString& aOSABI,
3912 nsIFile* aXULRunnerDir, nsIFile* aAppDir,
3913 nsIFile* aFlagFile) {
3914 CompatCheckResult result;
3915
3916 nsCOMPtr<nsIFile> file;
3917 aProfileDir->Clone(getter_AddRefs(file));
3918 if (!file) return result;
3919 file->AppendNative(FILE_COMPATIBILITY_INFO"compatibility.ini"_ns);
3920
3921 nsINIParsernsINIParser_internal parser;
3922 nsresult rv = parser.Init(file);
3923 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return result;
3924
3925 // The EncryptedDatabases marker is independent of version compatibility, so
3926 // read it here -- compatibility.ini is already parsed -- before the early
3927 // returns below. Consumed by the encryption gate in XRE_mainStartup.
3928 {
3929 nsAutoCString encBuf;
3930 result.hasEncryptedDatabases =
3931 NS_SUCCEEDED(((bool)(__builtin_expect(!!(!NS_FAILED_impl(parser.GetString(
"Compatibility", "EncryptedDatabases", encBuf))), 1)))
3932 parser.GetString("Compatibility", "EncryptedDatabases", encBuf))((bool)(__builtin_expect(!!(!NS_FAILED_impl(parser.GetString(
"Compatibility", "EncryptedDatabases", encBuf))), 1)))
&&
3933 encBuf.EqualsLiteral("1");
3934 }
3935
3936 rv = parser.GetString("Compatibility", "LastVersion", result.lastVersion);
3937 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
3938 return result;
3939 }
3940
3941 // Check whether this is the same install by comparing the platform and app
3942 // directories. Done before the version comparison so it is set even for
3943 // downgrades.
3944 result.isDifferentInstall = ![&]() {
3945 nsAutoCString dirBuf;
3946 nsCOMPtr<nsIFile> lf;
3947 bool eq = false;
3948
3949 if (NS_FAILED(((bool)(__builtin_expect(!!(NS_FAILED_impl(parser.GetString("Compatibility"
, "LastPlatformDir", dirBuf))), 0)))
3950 parser.GetString("Compatibility", "LastPlatformDir", dirBuf))((bool)(__builtin_expect(!!(NS_FAILED_impl(parser.GetString("Compatibility"
, "LastPlatformDir", dirBuf))), 0)))
||
3951 NS_FAILED(NS_NewLocalFileWithPersistentDescriptor(((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_NewLocalFileWithPersistentDescriptor
( dirBuf, getter_AddRefs(lf)))), 0)))
3952 dirBuf, getter_AddRefs(lf)))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_NewLocalFileWithPersistentDescriptor
( dirBuf, getter_AddRefs(lf)))), 0)))
||
3953 NS_FAILED(lf->Equals(aXULRunnerDir, &eq))((bool)(__builtin_expect(!!(NS_FAILED_impl(lf->Equals(aXULRunnerDir
, &eq))), 0)))
|| !eq) {
3954 return false;
3955 }
3956
3957 if (!aAppDir) {
3958 return true;
3959 }
3960
3961 if (NS_FAILED(parser.GetString("Compatibility", "LastAppDir", dirBuf))((bool)(__builtin_expect(!!(NS_FAILED_impl(parser.GetString("Compatibility"
, "LastAppDir", dirBuf))), 0)))
||
3962 NS_FAILED(NS_NewLocalFileWithPersistentDescriptor(((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_NewLocalFileWithPersistentDescriptor
( dirBuf, getter_AddRefs(lf)))), 0)))
3963 dirBuf, getter_AddRefs(lf)))((bool)(__builtin_expect(!!(NS_FAILED_impl(NS_NewLocalFileWithPersistentDescriptor
( dirBuf, getter_AddRefs(lf)))), 0)))
||
3964 NS_FAILED(lf->Equals(aAppDir, &eq))((bool)(__builtin_expect(!!(NS_FAILED_impl(lf->Equals(aAppDir
, &eq))), 0)))
|| !eq) {
3965 return false;
3966 }
3967
3968 return true;
3969 }();
3970
3971 if (!result.lastVersion.Equals(aVersion)) {
3972 // The version is not the same. Whether it's a downgrade depends on an
3973 // actual comparison:
3974 result.isDowngrade =
3975 0 < CompareCompatVersions(result.lastVersion, aVersion);
3976 ExtractCompatVersionInfo(result.lastVersion, result.lastAppVersion,
3977 result.lastAppBuildID);
3978 return result;
3979 }
3980
3981 // If we get here, the version matched, but there may still be other
3982 // differences between us and the build that the profile last ran under.
3983
3984 result.lastAppVersion.Assign(gAppData->version);
3985 result.lastAppBuildID.Assign(gAppData->buildID);
3986
3987 nsAutoCString buf;
3988 rv = parser.GetString("Compatibility", "LastOSABI", buf);
3989 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !aOSABI.Equals(buf)) return result;
3990
3991 if (result.isDifferentInstall) return result;
3992
3993 // If we see this flag, caches are invalid.
3994 rv = parser.GetString("Compatibility", "InvalidateCaches", buf);
3995 result.cachesOK = (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !buf.EqualsLiteral("1"));
3996
3997 bool purgeCaches = false;
3998 if (aFlagFile && NS_SUCCEEDED(aFlagFile->Exists(&purgeCaches))((bool)(__builtin_expect(!!(!NS_FAILED_impl(aFlagFile->Exists
(&purgeCaches))), 1)))
&&
3999 purgeCaches) {
4000 result.cachesOK = false;
4001 }
4002
4003 result.isCompatible = true;
4004 return result;
4005}
4006
4007void BuildCompatVersion(const char* aAppVersion, const char* aAppBuildID,
4008 const char* aToolkitBuildID, nsACString& aBuf) {
4009 aBuf.Assign(aAppVersion);
4010 aBuf.Append('_');
4011 aBuf.Append(aAppBuildID);
4012 aBuf.Append('/');
4013 aBuf.Append(aToolkitBuildID);
4014}
4015
4016static void BuildVersion(nsCString& aBuf) {
4017 BuildCompatVersion(gAppData->version, gAppData->buildID, gToolkitBuildID,
4018 aBuf);
4019}
4020
4021static void WriteVersion(nsIFile* aProfileDir, const nsCString& aVersion,
4022 const nsCString& aOSABI, nsIFile* aXULRunnerDir,
4023 nsIFile* aAppDir, bool invalidateCache) {
4024 nsCOMPtr<nsIFile> file;
4025 aProfileDir->Clone(getter_AddRefs(file));
4026 if (!file) return;
4027 file->AppendNative(FILE_COMPATIBILITY_INFO"compatibility.ini"_ns);
4028
4029 nsAutoCString platformDir;
4030 (void)aXULRunnerDir->GetPersistentDescriptor(platformDir);
4031
4032 nsAutoCString appDir;
4033 if (aAppDir) (void)aAppDir->GetPersistentDescriptor(appDir);
4034
4035 PRFileDesc* fd;
4036 nsresult rv = file->OpenNSPRFileDesc(PR_WRONLY0x02 | PR_CREATE_FILE0x08 | PR_TRUNCATE0x20,
4037 0600, &fd);
4038 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4039 NS_ERROR("could not create output stream")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "could not create output stream"
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
4039); MOZ_PretendNoReturn(); } while (0)
;
4040 return;
4041 }
4042
4043 static const char kHeader[] = "[Compatibility]" NS_LINEBREAK"\012" "LastVersion=";
4044
4045 PR_Write(fd, kHeader, sizeof(kHeader) - 1);
4046 PR_Write(fd, aVersion.get(), aVersion.Length());
4047
4048 static const char kOSABIHeader[] = NS_LINEBREAK"\012" "LastOSABI=";
4049 PR_Write(fd, kOSABIHeader, sizeof(kOSABIHeader) - 1);
4050 PR_Write(fd, aOSABI.get(), aOSABI.Length());
4051
4052 static const char kPlatformDirHeader[] = NS_LINEBREAK"\012" "LastPlatformDir=";
4053
4054 PR_Write(fd, kPlatformDirHeader, sizeof(kPlatformDirHeader) - 1);
4055 PR_Write(fd, platformDir.get(), platformDir.Length());
4056
4057 static const char kAppDirHeader[] = NS_LINEBREAK"\012" "LastAppDir=";
4058 if (aAppDir) {
4059 PR_Write(fd, kAppDirHeader, sizeof(kAppDirHeader) - 1);
4060 PR_Write(fd, appDir.get(), appDir.Length());
4061 }
4062
4063 static const char kInvalidationHeader[] = NS_LINEBREAK"\012" "InvalidateCaches=1";
4064 if (invalidateCache)
4065 PR_Write(fd, kInvalidationHeader, sizeof(kInvalidationHeader) - 1);
4066
4067 // Re-emit the SQLite at-rest encryption marker (set in
4068 // gProfileEncryptedDatabases by CheckCompatibility); WriteVersion truncates
4069 // compatibility.ini, so otherwise the marker is lost on update and the
4070 // next-startup encryption gate would mistake an encrypted profile for a
4071 // plaintext one.
4072 static const char kEncryptedHeader[] = NS_LINEBREAK"\012" "EncryptedDatabases=1";
4073 if (gProfileEncryptedDatabases)
4074 PR_Write(fd, kEncryptedHeader, sizeof(kEncryptedHeader) - 1);
4075
4076 static const char kNL[] = NS_LINEBREAK"\012";
4077 PR_Write(fd, kNL, sizeof(kNL) - 1);
4078
4079 PR_Close(fd);
4080}
4081
4082// Read the first 24 bytes of the first existing canonical app DB and
4083// classify its encryption state by header inspection. No SQLite, no
4084// mozStorage -- a pure file read. Returns NoDBs if none of the canonical
4085// DBs exist in the profile.
4086enum class DBHeaderResult { Encrypted, Plaintext, NoDBs };
4087
4088static DBHeaderResult DetectEncryptedDBHeader(nsIFile* aProfileDir) {
4089 // Canonical DB list: any one of these existing is evidence of a
4090 // non-fresh profile. Order matters for cheapness only.
4091 static const char* const kCandidates[] = {
4092 "cookies.sqlite", "places.sqlite", "permissions.sqlite",
4093 "storage.sqlite", "favicons.sqlite",
4094 };
4095
4096 for (const char* name : kCandidates) {
4097 nsCOMPtr<nsIFile> file;
4098 if (NS_FAILED(aProfileDir->Clone(getter_AddRefs(file)))((bool)(__builtin_expect(!!(NS_FAILED_impl(aProfileDir->Clone
(getter_AddRefs(file)))), 0)))
|| !file) continue;
4099 if (NS_FAILED(file->AppendNative(nsDependentCString(name)))((bool)(__builtin_expect(!!(NS_FAILED_impl(file->AppendNative
(nsDependentCString(name)))), 0)))
) continue;
4100
4101 bool exists = false;
4102 if (NS_FAILED(file->Exists(&exists))((bool)(__builtin_expect(!!(NS_FAILED_impl(file->Exists(&
exists))), 0)))
|| !exists) continue;
4103
4104 PRFileDesc* fd = nullptr;
4105 if (NS_FAILED(file->OpenNSPRFileDesc(PR_RDONLY, 0, &fd))((bool)(__builtin_expect(!!(NS_FAILED_impl(file->OpenNSPRFileDesc
(0x01, 0, &fd))), 0)))
|| !fd) continue;
4106
4107 // SQLite database header layout (https://sqlite.org/fileformat.html): the
4108 // page size is a big-endian u16 at offset 16 and the per-page reserved-byte
4109 // count is a u8 at offset 20. obfsvfs always writes 8192-byte pages with 32
4110 // reserved bytes, which is how an at-rest-encrypted database is recognized.
4111 static constexpr int32_t kSQLiteHeaderReadBytes = 24;
4112 static constexpr int32_t kSQLiteHeaderMinBytes = 21;
4113 static constexpr size_t kSQLitePageSizeOffset = 16;
4114 static constexpr size_t kSQLiteReservedOffset = 20;
4115 static constexpr uint16_t kObfsPageSize = 8192;
4116 static constexpr uint8_t kObfsReservedBytes = 32;
4117
4118 uint8_t hdr[kSQLiteHeaderReadBytes];
4119 int32_t got = PR_Read(fd, hdr, sizeof(hdr));
4120 PR_Close(fd);
4121 if (got < kSQLiteHeaderMinBytes) continue;
4122
4123 uint16_t pageSize = (uint16_t(hdr[kSQLitePageSizeOffset]) << 8) |
4124 uint16_t(hdr[kSQLitePageSizeOffset + 1]);
4125 uint8_t reserved = hdr[kSQLiteReservedOffset];
4126
4127 if (pageSize == kObfsPageSize && reserved == kObfsReservedBytes) {
4128 return DBHeaderResult::Encrypted;
4129 }
4130 return DBHeaderResult::Plaintext;
4131 }
4132 return DBHeaderResult::NoDBs;
4133}
4134
4135enum class EncryptionCompatResult {
4136 OK,
4137 RefuseEncryptedButPrefOff,
4138 RefuseMigrationRequired,
4139};
4140
4141// Decide whether the on-disk state and the launching build's encryption
4142// pref are compatible. Must be called after CheckCompatibility() has run
4143// (it populates gProfileEncryptedDatabases). aPrefEnabled is the current
4144// value of security.storage.encryption.sqlite.enabled.
4145static EncryptionCompatResult CheckEncryptionCompatibility(nsIFile* aProfileDir,
4146 bool aPrefEnabled) {
4147 // Pref off: we cannot read an encrypted profile, so refuse it. The marker is
4148 // the fast path, but it can be absent on a profile that a prior build
4149 // encrypted without recording it (e.g. storage initialized too late to
4150 // mark), so also inspect the on-disk headers. The probe runs only when the
4151 // marker is absent, so the common (plaintext, never-encrypted) profile pays
4152 // it once at startup; an encrypted-looking profile is hard-failed rather
4153 // than opened as plaintext and corrupted.
4154 if (!aPrefEnabled) {
4155 if (gProfileEncryptedDatabases ||
4156 DetectEncryptedDBHeader(aProfileDir) == DBHeaderResult::Encrypted) {
4157 return EncryptionCompatResult::RefuseEncryptedButPrefOff;
4158 }
4159 return EncryptionCompatResult::OK;
4160 }
4161
4162 // Pref on, marker absent (or =0). Disambiguate by header inspection:
4163 // - empty profile or already-encrypted DBs -> OK (the marker is
4164 // (re)written by the storage layer on profile-after-change).
4165 // - plaintext DBs present -> refuse, migration required.
4166 if (!gProfileEncryptedDatabases &&
4167 DetectEncryptedDBHeader(aProfileDir) == DBHeaderResult::Plaintext) {
4168 return EncryptionCompatResult::RefuseMigrationRequired;
4169 }
4170
4171 return EncryptionCompatResult::OK;
4172}
4173
4174/**
4175 * Returns true if the startup cache file was successfully removed.
4176 * Returns false if file->Clone fails at any point (OOM) or if unable
4177 * to remove the startup cache file. Note in particular the return value
4178 * is unaffected by a failure to remove extensions.ini
4179 */
4180static bool RemoveComponentRegistries(nsIFile* aProfileDir,
4181 nsIFile* aLocalProfileDir,
4182 bool aRemoveEMFiles) {
4183 nsCOMPtr<nsIFile> file;
4184 aProfileDir->Clone(getter_AddRefs(file));
4185 if (!file) return false;
4186
4187 if (aRemoveEMFiles) {
4188 file->SetNativeLeafName("extensions.ini"_ns);
4189 file->Remove(false);
4190 }
4191
4192 aLocalProfileDir->Clone(getter_AddRefs(file));
4193 if (!file) return false;
4194
4195 file->AppendNative("startupCache"_ns);
4196 nsresult rv = file->Remove(true);
4197 return NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) || rv == NS_ERROR_FILE_NOT_FOUND;
4198}
4199
4200// When we first initialize the crash reporter we don't have a profile,
4201// so we set the minidump path to $TEMP. Once we have a profile,
4202// we set it to $PROFILE/minidumps, creating the directory
4203// if needed.
4204static void MakeOrSetMinidumpPath(nsIFile* profD) {
4205 nsCOMPtr<nsIFile> dumpD;
4206 profD->Clone(getter_AddRefs(dumpD));
4207
4208 if (dumpD) {
4209 bool fileExists;
4210 // XXX: do some more error checking here
4211 dumpD->Append(u"minidumps"_ns);
4212 dumpD->Exists(&fileExists);
4213 if (!fileExists) {
4214 nsresult rv = dumpD->Create(nsIFile::DIRECTORY_TYPE, 0700);
4215 NS_ENSURE_SUCCESS_VOID(rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS_VOID(%s) failed with "
"result 0x%" "X" "%s%s%s", "rv", static_cast<uint32_t>
(__rv), name ? " (" : "", name ? name : "", name ? ")" : "");
NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 4215); return; } } while (false)
;
4216 }
4217
4218 nsAutoString pathStr;
4219 if (NS_SUCCEEDED(dumpD->GetPath(pathStr))((bool)(__builtin_expect(!!(!NS_FAILED_impl(dumpD->GetPath
(pathStr))), 1)))
)
4220 CrashReporter::SetMinidumpPath(pathStr);
4221 }
4222}
4223
4224const XREAppData* gAppData = nullptr;
4225
4226/**
4227 * NSPR will search for the "nspr_use_zone_allocator" symbol throughout
4228 * the process and use it to determine whether the application defines its own
4229 * memory allocator or not.
4230 *
4231 * Since most applications (e.g. Firefox and Thunderbird) don't use any special
4232 * allocators and therefore don't define this symbol, NSPR must search the
4233 * entire process, which reduces startup performance.
4234 *
4235 * By defining the symbol here, we can avoid the wasted lookup and hopefully
4236 * improve startup performance.
4237 */
4238NS_VISIBILITY_DEFAULT__attribute__((visibility("default"))) PRBool nspr_use_zone_allocator = PR_FALSE0;
4239
4240#ifdef CAIRO_HAS_DWRITE_FONT
4241
4242# include <dwrite.h>
4243# include "nsWindowsHelpers.h"
4244
4245# ifdef DEBUG_DWRITE_STARTUP
4246
4247# define LOGREGISTRY(msg) LogRegistryEvent(msg)
4248
4249// for use when monitoring process
4250static void LogRegistryEvent(const wchar_t* msg) {
4251 HKEY dummyKey;
4252 HRESULT hr;
4253 wchar_t buf[512];
4254
4255 wsprintf(buf, L" log %s", msg);
4256 hr = RegOpenKeyEx(HKEY_LOCAL_MACHINE, buf, 0, KEY_READ, &dummyKey);
4257 if (SUCCEEDED(hr)) {
4258 RegCloseKey(dummyKey);
4259 }
4260}
4261# else
4262
4263# define LOGREGISTRY(msg)
4264
4265# endif
4266
4267static DWORD WINAPI InitDwriteBG(LPVOID lpdwThreadParam) {
4268 SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);
4269 LOGREGISTRY(L"loading dwrite.dll");
4270 HMODULE dwdll = LoadLibrarySystem32(L"dwrite.dll");
4271 if (dwdll) {
4272 decltype(DWriteCreateFactory)* createDWriteFactory =
4273 (decltype(DWriteCreateFactory)*)GetProcAddress(dwdll,
4274 "DWriteCreateFactory");
4275 if (createDWriteFactory) {
4276 LOGREGISTRY(L"creating dwrite factory");
4277 IDWriteFactory* factory;
4278 HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED,
4279 __uuidof(IDWriteFactory),
4280 reinterpret_cast<IUnknown**>(&factory));
4281 if (SUCCEEDED(hr)) {
4282 LOGREGISTRY(L"dwrite factory done");
4283 factory->Release();
4284 LOGREGISTRY(L"freed factory");
4285 } else {
4286 LOGREGISTRY(L"failed to create factory");
4287 }
4288 }
4289 }
4290 SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);
4291 return 0;
4292}
4293#endif
4294
4295#include "GeckoProfiler.h"
4296#include "ProfilerControl.h"
4297
4298// Encapsulates startup and shutdown state for XRE_main
4299class XREMain {
4300 public:
4301 XREMain() = default;
4302
4303 ~XREMain() {
4304 mScopedXPCOM = nullptr;
4305 mAppData = nullptr;
4306 }
4307
4308 MOZ_CAN_RUN_SCRIPT
4309 int XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig);
4310 int XRE_mainInit(bool* aExitFlag);
4311 MOZ_CAN_RUN_SCRIPT
4312 int XRE_mainStartup(bool* aExitFlag);
4313 MOZ_CAN_RUN_SCRIPT_BOUNDARY nsresult XRE_mainRun();
4314
4315 bool CheckLastStartupWasCrash();
4316
4317 nsCOMPtr<nsINativeAppSupport> mNativeApp;
4318 RefPtr<nsToolkitProfileService> mProfileSvc;
4319 nsCOMPtr<nsIFile> mProfD;
4320 nsCOMPtr<nsIFile> mProfLD;
4321 nsCOMPtr<nsIProfileLock> mProfileLock;
4322
4323 UniquePtr<ScopedXPCOMStartup> mScopedXPCOM;
4324 UniquePtr<XREAppData> mAppData;
4325
4326 nsXREDirProvider mDirProvider;
4327
4328#ifdef MOZ_WIDGET_GTK1
4329 nsAutoCString mXDGActivationToken;
4330 nsAutoCString mDesktopStartupID;
4331#endif
4332
4333 bool mStartOffline = false;
4334 nsAutoCString mOriginToForceQUIC;
4335#if defined(MOZ_HAS_REMOTE1)
4336 bool mDisableRemoteClient = false;
4337#endif
4338};
4339
4340#if defined(XP_UNIX1) && !defined(ANDROID)
4341static SmprintfPointer FormatUid(uid_t aId) {
4342 if (const auto pw = getpwuid(aId)) {
4343 return mozilla::Smprintf("%s", pw->pw_name);
4344 }
4345 return mozilla::Smprintf("uid %d", static_cast<int>(aId));
4346}
4347
4348// Bug 1323302: refuse to run under sudo or similar.
4349static bool CheckForUserMismatch() {
4350 static char const* const kVars[] = {
4351 "HOME",
4352# ifdef MOZ_WIDGET_GTK1
4353 "XDG_RUNTIME_DIR",
4354# endif
4355# ifdef MOZ_X111
4356 "XAUTHORITY",
4357# endif
4358 };
4359
4360 const uid_t euid = geteuid();
4361 if (euid != 0) {
4362 // On Linux it's possible to have superuser capabilities with a
4363 // nonzero uid, but anyone who knows enough to make that happen
4364 // probably knows enough to debug the resulting problems.
4365 // Otherwise, a non-root user can't cause the problems we're
4366 // concerned about.
4367 return false;
4368 }
4369
4370 for (const auto var : kVars) {
4371 if (const auto path = PR_GetEnv(var)) {
4372 struct stat st;
4373 if (stat(path, &st) == 0) {
4374 if (st.st_uid != euid) {
4375 const auto owner = FormatUid(st.st_uid);
4376 Output(true,
4377 "Running " MOZ_APP_DISPLAYNAME"Nightly"
4378 " as root in a regular"
4379 " user's session is not supported. ($%s is %s which is"
4380 " owned by %s.)\n",
4381 var, path, owner.get());
4382 return true;
4383 }
4384 }
4385 }
4386 }
4387 return false;
4388}
4389#else // !XP_UNIX || ANDROID
4390static bool CheckForUserMismatch() { return false; }
4391#endif
4392
4393void mozilla::startup::IncreaseDescriptorLimits() {
4394#ifdef XP_UNIX1
4395 // Increase the fd limit to accommodate IPC resources like shared memory.
4396 // This can be increased if needed, but also be aware that Linux
4397 // distributions may impose hard limits less than this. macOS accepts any
4398 // value and caps the effective limit at kern.maxfilesperproc, and it must
4399 // not exceed the FD_SETSIZE in config/external/nspr/pr/moz.build.
4400 static constexpr rlim_t kFDs = 65536;
4401 struct rlimit rlim;
4402
4403 if (getrlimit(RLIMIT_NOFILERLIMIT_NOFILE, &rlim) != 0) {
4404 Output(false, "getrlimit: %s\n", strerror(errno(*__errno_location ())));
4405 return;
4406 }
4407 // Don't decrease the limit if it's already high enough, but don't
4408 // try to go over the hard limit. (RLIM_INFINITY isn't required to
4409 // be the numerically largest rlim_t, so don't assume that.)
4410 if (rlim.rlim_cur != RLIM_INFINITY((__rlim_t) -1) && rlim.rlim_cur < kFDs &&
4411 rlim.rlim_cur < rlim.rlim_max) {
4412 if (rlim.rlim_max != RLIM_INFINITY((__rlim_t) -1) && rlim.rlim_max < kFDs) {
4413 rlim.rlim_cur = rlim.rlim_max;
4414 } else {
4415 rlim.rlim_cur = kFDs;
4416 }
4417 if (setrlimit(RLIMIT_NOFILERLIMIT_NOFILE, &rlim) != 0) {
4418 Output(false, "setrlimit: %s\n", strerror(errno(*__errno_location ())));
4419 }
4420 }
4421#endif
4422}
4423
4424#ifdef XP_WIN
4425// Looks for the current CPU microcode version, returns 0 if it cannot find it
4426static uint32_t FindCPUMicrocodeVersion(HKEY key) {
4427 // Windows uses different registry values to surface the current microcode
4428 // value, and sometimes different update levels of the same version use
4429 // different values (e.g. Windows 11 24H2 uses "Current Record Version",
4430 // older Windows 11 and Windows 8/10 use "Update Revision", Windows 7 uses
4431 // "Update Signature" or sometimes "CurrentPatchLevel" for AMD CPUs.
4432 // Microcode version is represented by a 32-bit value but sometimes a 64-bit
4433 // value is surfaced instead with only half of it populated (e.g.
4434 // "Update Revision" on Windows 8, 10 and 11 pre-24H2). Since in these cases
4435 // the other half is zero, we pick the first non-zero 32-bit value we find
4436 // starting with the most "modern" registry value.
4437 LPCWSTR choices[] = {L"Current Record Version", L"Update Revision",
4438 L"Update Signature", L"CurrentPatchLevel"};
4439 for (const auto& oneChoice : choices) {
4440 DWORD keyValue[2] = {};
4441 DWORD len = sizeof(keyValue);
4442 DWORD vtype;
4443
4444 if (RegQueryValueExW(key, oneChoice, nullptr, &vtype,
4445 reinterpret_cast<LPBYTE>(keyValue),
4446 &len) == ERROR_SUCCESS) {
4447 if ((vtype == REG_BINARY) || (vtype == REG_DWORD)) {
4448 for (size_t i = 0; i < (len / sizeof(DWORD)); i++) {
4449 uint32_t value = keyValue[i];
4450
4451 if (value != 0) {
4452 return value;
4453 }
4454 }
4455 }
4456 }
4457 }
4458
4459 return 0;
4460}
4461#endif
4462
4463static void MaybeAddCPUMicrocodeCrashAnnotation() {
4464#ifdef XP_WIN
4465 // Add CPU microcode version to the crash report as "CPUMicrocodeVersion".
4466 // It feels like this code may belong in nsSystemInfo instead.
4467 HKEY key;
4468 static const WCHAR keyName[] =
4469 L"HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0";
4470
4471 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, keyName, 0, KEY_QUERY_VALUE, &key) ==
4472 ERROR_SUCCESS) {
4473 uint32_t cpuMicrocodeVersion = FindCPUMicrocodeVersion(key);
4474
4475 if (cpuMicrocodeVersion != 0) {
4476 CrashReporter::RecordAnnotationNSCString(
4477 CrashReporter::Annotation::CPUMicrocodeVersion,
4478 nsPrintfCString("0x%" PRIx32"x", cpuMicrocodeVersion));
4479 }
4480 }
4481#endif
4482}
4483
4484#if defined(MOZ_BACKGROUNDTASKS1)
4485static void SetupConsoleForBackgroundTask(
4486 const nsCString& aBackgroundTaskName) {
4487 // We do not suppress output on Windows because:
4488 // 1. Background task subprocesses launched via LaunchApp() does not attach to
4489 // the console.
4490 // 2. Suppressing output intermittently causes failures on when running
4491 // multiple tasks (see bug 1831631)
4492# ifndef XP_WIN
4493 if (BackgroundTasks::IsNoOutputTaskName(aBackgroundTaskName) &&
4494 !CheckArg("attach-console") &&
4495 !EnvHasValue("MOZ_BACKGROUNDTASKS_IGNORE_NO_OUTPUT")) {
4496 // Suppress output, somewhat crudely. We need to suppress stderr as well
4497 // as stdout because assertions, of which there are many, write to stderr.
4498 [[maybe_unused]] FILE* r0 = freopen("/dev/null", "w", stdoutstdout);
4499 [[maybe_unused]] FILE* r1 = freopen("/dev/null", "w", stderrstderr);
4500 return;
4501 }
4502# endif
4503 printf_stderr("*** You are running in background task mode. ***\n");
4504}
4505#endif
4506
4507/*
4508 * XRE_mainInit - Initial setup and command line parameter processing.
4509 * Main() will exit early if either return value != 0 or if aExitFlag is
4510 * true.
4511 */
4512int XREMain::XRE_mainInit(bool* aExitFlag) {
4513 if (!aExitFlag) return 1;
4514 *aExitFlag = false;
4515
4516 atexit(UnexpectedExit);
4517 auto expectedShutdown = mozilla::MakeScopeExit([&] { MozExpectedExit(); });
4518
4519 StartupTimeline::Record(StartupTimeline::MAIN);
4520
4521 // On Windows, to get working console arrangements so help/version/etc
4522 // print something, we need to initialize the native app support.
4523 nsresult rv = NS_CreateNativeAppSupport(getter_AddRefs(mNativeApp));
4524 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return 1;
4525
4526 // Handle --*version arguments early to avoid initializing full XPCOM.
4527 // Note: we *cannot* handle --help here, as it requires more components
4528 // to be initialized.
4529 if (CheckArg("v") || CheckArg("version")) {
4530 DumpVersion();
4531 *aExitFlag = true;
4532 return 0;
4533 }
4534
4535 if (CheckArg("full-version")) {
4536 DumpFullVersion();
4537 *aExitFlag = true;
4538 return 0;
4539 }
4540
4541 if (CheckForUserMismatch()) {
4542 return 1;
4543 }
4544
4545#ifdef XP_MACOSX
4546 mozilla::MacAutoreleasePool pool;
4547
4548 DisableAppNap();
4549#endif
4550
4551#ifdef MOZ_BACKGROUNDTASKS1
4552 Maybe<nsCString> backgroundTask = Nothing();
4553 const char* backgroundTaskName = nullptr;
4554 if (ARG_FOUND ==
4555 CheckArg("backgroundtask", &backgroundTaskName, CheckArgFlag::None)) {
4556 backgroundTask = Some(backgroundTaskName);
4557 SetupConsoleForBackgroundTask(backgroundTask.ref());
4558 }
4559
4560 BackgroundTasks::Init(backgroundTask);
4561#endif
4562
4563#ifndef ANDROID
4564 if (PR_GetEnv("MOZ_RUN_GTEST")
4565# ifdef FUZZING
4566 || PR_GetEnv("FUZZER")
4567# endif
4568# ifdef MOZ_BACKGROUNDTASKS1
4569 || BackgroundTasks::IsBackgroundTaskMode()
4570# endif
4571 ) {
4572 // Enable headless mode and assert that it worked, since gfxPlatform
4573 // uses a static bool set after the first call to `IsHeadless`.
4574 // Note: Android gtests seem to require an Activity and fail to start
4575 // with headless mode enabled.
4576 PR_SetEnv("MOZ_HEADLESS=1");
4577 MOZ_ASSERT(gfxPlatform::IsHeadless())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(gfxPlatform::IsHeadless())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(gfxPlatform::IsHeadless())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("gfxPlatform::IsHeadless()"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 4577); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "gfxPlatform::IsHeadless()" ")"); do { MOZ_CrashSequence
(__null, 4577); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
4578 }
4579#endif // ANDROID
4580
4581 if (auto* featureStr = PR_GetEnv("MOZ_CHAOSMODE")) {
4582 ChaosFeature feature = ChaosFeature::Any;
4583 long featureInt = strtol(featureStr, nullptr, 16);
4584 if (featureInt) {
4585 // NOTE: MOZ_CHAOSMODE=0 or a non-hex value maps to Any feature.
4586 feature = static_cast<ChaosFeature>(featureInt);
4587 }
4588 ChaosMode::SetChaosFeature(feature);
4589 ChaosMode::enterChaosMode();
4590 MOZ_ASSERT(ChaosMode::isActive(ChaosFeature::Any))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ChaosMode::isActive(ChaosFeature::Any))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(ChaosMode::isActive(ChaosFeature::Any)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("ChaosMode::isActive(ChaosFeature::Any)"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 4590); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "ChaosMode::isActive(ChaosFeature::Any)" ")"
); do { MOZ_CrashSequence(__null, 4590); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4591 }
4592
4593 if (CheckArgExists("fxr")) {
4594 gFxREmbedded = true;
4595 }
4596
4597 if (ChaosMode::isActive(ChaosFeature::Any)) {
4598 printf_stderr(
4599 "*** You are running in chaos test mode. See ChaosMode.h. ***\n");
4600 }
4601
4602 if (CheckArg("headless") || CheckArgExists("screenshot")) {
4603 PR_SetEnv("MOZ_HEADLESS=1");
4604 }
4605
4606 if (gfxPlatform::IsHeadless()) {
4607#if defined(XP_WIN) || defined(MOZ_WIDGET_GTK1) || defined(XP_MACOSX)
4608 printf_stderr("*** You are running in headless mode.\n");
4609#else
4610 Output(
4611 true,
4612 "Error: headless mode is not currently supported on this platform.\n");
4613 return 1;
4614#endif
4615
4616#ifdef XP_MACOSX
4617 // To avoid taking focus when running in headless mode immediately
4618 // transition Firefox to a background application.
4619 ProcessSerialNumber psn = {0, kCurrentProcess};
4620 OSStatus transformStatus =
4621 TransformProcessType(&psn, kProcessTransformToBackgroundApplication);
4622 if (transformStatus != noErr) {
4623 NS_ERROR("Failed to make process a background application.")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "Failed to make process a background application."
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
4623); MOZ_PretendNoReturn(); } while (0)
;
4624 return 1;
4625 }
4626#endif
4627 }
4628
4629 gKioskMode = CheckArg("kiosk", nullptr, CheckArgFlag::None);
4630 const char* kioskMonitorNumber = nullptr;
4631 if (CheckArg("kiosk-monitor", &kioskMonitorNumber, CheckArgFlag::None)) {
4632 gKioskMode = true;
4633 gKioskMonitor = atoi(kioskMonitorNumber);
4634 }
4635
4636#if defined(NIGHTLY_BUILD1)
4637 if (XRE_IsParentProcess()) {
4638 gAllowContentAnalysisArgPresent =
4639 CheckArg("allow-content-analysis", nullptr, CheckArgFlag::None) ==
4640 ARG_FOUND;
4641 }
4642#endif
4643
4644 ArgResult ar;
4645
4646#ifdef DEBUG1
4647 if (PR_GetEnv("XRE_MAIN_BREAK")) NS_BREAK()do { NS_DebugBreak(NS_DEBUG_BREAK, nullptr, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 4647); MOZ_PretendNoReturn(); } while (0)
;
4648#endif
4649
4650 mozilla::startup::IncreaseDescriptorLimits();
4651
4652 SetupErrorHandling(gArgv[0]);
4653
4654#ifdef CAIRO_HAS_DWRITE_FONT
4655 {
4656 // Bug 602792 - when DWriteCreateFactory is called the dwrite client dll
4657 // starts the FntCache service if it isn't already running (it's set
4658 // to manual startup by default in Windows 7 RTM). Subsequent DirectWrite
4659 // calls cause the IDWriteFactory object to communicate with the FntCache
4660 // service with a timeout; if there's no response after the timeout, the
4661 // DirectWrite client library will assume the service isn't around and do
4662 // manual font file I/O on _all_ system fonts. To avoid this, load the
4663 // dwrite library and create a factory as early as possible so that the
4664 // FntCache service is ready by the time it's needed.
4665
4666 CreateThread(nullptr, 0, &InitDwriteBG, nullptr, 0, nullptr);
4667 }
4668#endif
4669
4670#ifdef XP_UNIX1
4671 const char* home = PR_GetEnv("HOME");
4672 if (!home || !*home) {
4673 struct passwd* pw = getpwuid(geteuid());
4674 if (!pw || !pw->pw_dir) {
4675 Output(true, "Could not determine HOME directory");
4676 return 1;
4677 }
4678 SaveWordToEnv("HOME", nsDependentCString(pw->pw_dir));
4679 }
4680#endif
4681
4682#ifdef MOZ_ACCESSIBILITY_ATK1
4683 // Suppress atk-bridge init at startup, until mozilla accessibility is
4684 // initialized. This works after gnome 2.24.2.
4685 SaveToEnv("NO_AT_BRIDGE=1");
4686#endif
4687
4688 // Check for application.ini overrides
4689 const char* override = nullptr;
4690 ar = CheckArg("override", &override);
4691 if (ar == ARG_BAD) {
4692 Output(true, "Incorrect number of arguments passed to --override");
4693 return 1;
4694 }
4695 if (ar == ARG_FOUND) {
4696 nsCOMPtr<nsIFile> overrideLF;
4697 rv = XRE_GetFileFromPath(override, getter_AddRefs(overrideLF));
4698 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4699 Output(true, "Error: unrecognized override.ini path.\n");
4700 return 1;
4701 }
4702
4703 rv = XRE_ParseAppData(overrideLF, *mAppData);
4704 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
4705 Output(true, "Couldn't read override.ini");
4706 return 1;
4707 }
4708 }
4709
4710 // Check sanity and correctness of app data.
4711
4712 if (!mAppData->name) {
4713 Output(true, "Error: App:Name not specified in application.ini\n");
4714 return 1;
4715 }
4716 if (!mAppData->buildID) {
4717 Output(true, "Error: App:BuildID not specified in application.ini\n");
4718 return 1;
4719 }
4720
4721 // XXX Originally ScopedLogging was here? Now it's in XRE_main above
4722 // XRE_mainInit.
4723
4724 if (!mAppData->minVersion) {
4725 Output(true, "Error: Gecko:MinVersion not specified in application.ini\n");
4726 return 1;
4727 }
4728
4729 if (!mAppData->maxVersion) {
4730 // If no maxVersion is specified, we assume the app is only compatible
4731 // with the initial preview release. Do not increment this number ever!
4732 mAppData->maxVersion = "1.*";
4733 }
4734
4735 if (mozilla::Version(mAppData->minVersion) > gToolkitVersion ||
4736 mozilla::Version(mAppData->maxVersion) < gToolkitVersion) {
4737 Output(true,
4738 "Error: Platform version '%s' is not compatible with\n"
4739 "minVersion >= %s\nmaxVersion <= %s\n"
4740 "Maybe try to reinstall " MOZ_APP_DISPLAYNAME"Nightly" "?\n",
4741 (const char*)gToolkitVersion, (const char*)mAppData->minVersion,
4742 (const char*)mAppData->maxVersion);
4743 return 1;
4744 }
4745
4746 rv = mDirProvider.Initialize(mAppData->directory, mAppData->xreDirectory);
4747 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return 1;
4748
4749 if (EnvHasValue("MOZ_CRASHREPORTER")) {
4750 mAppData->flags |= NS_XRE_ENABLE_CRASH_REPORTER(1 << 3);
4751 }
4752
4753#ifdef MOZ_THUNDERBIRD
4754 // Set an explicit application name for Thunderbird.
4755 // We do NOT set one for `firefox`.
4756 // FOG uses a default one,
4757 // background tasks overwrite it using `initializeFOG`.
4758 FOG::SetApplicationID("thunderbird.desktop"_ns);
4759#endif // MOZ_THUNDERBIRD
4760
4761 nsCOMPtr<nsIFile> xreBinDirectory;
4762 xreBinDirectory = mDirProvider.GetGREBinDir();
4763
4764 // Unconditionally set the ServerURL exception before we launch the crash
4765 // helper or set the exception handler. This guarantees that the annotation
4766 // will be populated when we need it.
4767 if (mAppData->crashReporterURL) {
4768 CrashReporter::SetServerURL(nsDependentCString(mAppData->crashReporterURL));
4769 }
4770
4771 if ((mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER(1 << 3)) &&
4772 NS_FAILED(CrashReporter::OOPInit(xreBinDirectory))((bool)(__builtin_expect(!!(NS_FAILED_impl(CrashReporter::OOPInit
(xreBinDirectory))), 0)))
) {
4773 NS_WARNING("Could not launch the crash helper")NS_DebugBreak(NS_DEBUG_WARNING, "Could not launch the crash helper"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
4773)
;
4774 }
4775
4776 if ((mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER(1 << 3)) &&
4777 NS_SUCCEEDED(CrashReporter::SetExceptionHandler(xreBinDirectory))((bool)(__builtin_expect(!!(!NS_FAILED_impl(CrashReporter::SetExceptionHandler
(xreBinDirectory))), 1)))
) {
4778 nsCOMPtr<nsIFile> file;
4779 rv = nsXREDirProvider::GetUserAppDataDirectory(getter_AddRefs(file));
4780 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
4781 CrashReporter::SetUserAppDataDirectory(file);
4782 }
4783
4784 // We overwrite this once we finish starting up.
4785 CrashReporter::RecordAnnotationBool(CrashReporter::Annotation::StartupCrash,
4786 true);
4787
4788 // pass some basic info from the app data
4789 if (mAppData->vendor) {
4790 CrashReporter::RecordAnnotationCString(CrashReporter::Annotation::Vendor,
4791 mAppData->vendor);
4792 }
4793 if (mAppData->name) {
4794 CrashReporter::RecordAnnotationCString(
4795 CrashReporter::Annotation::ProductName, mAppData->name);
4796 }
4797 if (mAppData->ID) {
4798 CrashReporter::RecordAnnotationCString(
4799 CrashReporter::Annotation::ProductID, mAppData->ID);
4800 }
4801 if (mAppData->version) {
4802 CrashReporter::RecordAnnotationCString(CrashReporter::Annotation::Version,
4803 mAppData->version);
4804 }
4805 if (mAppData->buildID) {
4806 CrashReporter::RecordAnnotationCString(CrashReporter::Annotation::BuildID,
4807 mAppData->buildID);
4808 }
4809
4810 nsDependentCString releaseChannel(MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL)"default");
4811 CrashReporter::RecordAnnotationNSCString(
4812 CrashReporter::Annotation::ReleaseChannel, releaseChannel);
4813
4814 CrashReporter::RecordPlatformAnnotations();
4815
4816#ifdef XP_WIN
4817 nsAutoString appInitDLLs;
4818 if (widget::WinUtils::GetAppInitDLLs(appInitDLLs)) {
4819 CrashReporter::RecordAnnotationNSString(
4820 CrashReporter::Annotation::AppInitDLLs, appInitDLLs);
4821 }
4822
4823 nsString packageFamilyName = widget::WinUtils::GetPackageFamilyName();
4824 if (StringBeginsWith(packageFamilyName, u"Mozilla."_ns) ||
4825 StringBeginsWith(packageFamilyName, u"MozillaCorporation."_ns)) {
4826 CrashReporter::RecordAnnotationNSCString(
4827 CrashReporter::Annotation::WindowsPackageFamilyName,
4828 NS_ConvertUTF16toUTF8(packageFamilyName));
4829 }
4830#endif
4831
4832 bool isBackgroundTaskMode = false;
4833#ifdef MOZ_BACKGROUNDTASKS1
4834 Maybe<nsCString> backgroundTasks = BackgroundTasks::GetBackgroundTasks();
4835 if (backgroundTasks.isSome()) {
4836 isBackgroundTaskMode = true;
4837 CrashReporter::RecordAnnotationNSCString(
4838 CrashReporter::Annotation::BackgroundTaskName, backgroundTasks.ref());
4839 }
4840#endif
4841 CrashReporter::RecordAnnotationBool(
4842 CrashReporter::Annotation::BackgroundTaskMode, isBackgroundTaskMode);
4843
4844 CrashReporter::RecordAnnotationBool(CrashReporter::Annotation::HeadlessMode,
4845 gfxPlatform::IsHeadless());
4846
4847 CrashReporter::SetRestartArgs(gArgc, gArgv);
4848
4849 // annotate other data (user id etc)
4850 nsCOMPtr<nsIFile> userAppDataDir;
4851 if (NS_SUCCEEDED(mDirProvider.GetUserAppDataDirectory(((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDirProvider.GetUserAppDataDirectory
( getter_AddRefs(userAppDataDir)))), 1)))
4852 getter_AddRefs(userAppDataDir)))((bool)(__builtin_expect(!!(!NS_FAILED_impl(mDirProvider.GetUserAppDataDirectory
( getter_AddRefs(userAppDataDir)))), 1)))
) {
4853 CrashReporter::SetupExtraData(userAppDataDir, mAppData->xreDirectory);
4854 }
4855 } else {
4856 // We might have registered a runtime exception module very early in process
4857 // startup to catch early crashes. This is before we have access to ini file
4858 // data, so unregister here if it turns out the crash reporter is disabled.
4859 CrashReporter::UnregisterRuntimeExceptionModule();
4860 }
4861
4862#if defined(MOZ_SANDBOX1) && defined(XP_WIN)
4863 if (mAppData->sandboxBrokerServices) {
4864 nsAutoString binDirPath;
4865 MOZ_ALWAYS_SUCCEEDS(xreBinDirectory->GetPath(binDirPath))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(xreBinDirectory->GetPath(binDirPath))), 1)))), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(xreBinDirectory->GetPath(binDirPath))"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 4865); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_SUCCEEDED(xreBinDirectory->GetPath(binDirPath))"
")"); do { MOZ_CrashSequence(__null, 4865); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
4866 SandboxBroker::Initialize(mAppData->sandboxBrokerServices, binDirPath);
4867 } else {
4868# if defined(MOZ_SANDBOX1)
4869 // If we're sandboxing content and we fail to initialize, then crashing here
4870 // seems like the sensible option.
4871 if (BrowserTabsRemoteAutostart()) {
4872 MOZ_CRASH("Failed to initialize broker services, can't continue.")do { do { } while (false); MOZ_ReportCrash("" "Failed to initialize broker services, can't continue."
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 4872); AnnotateMozCrashReason
("MOZ_CRASH(" "Failed to initialize broker services, can't continue."
")"); do { MOZ_CrashSequence(__null, 4872); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
4873 }
4874# endif
4875 // Otherwise just warn for the moment, as most things will work.
4876 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Failed to initialize broker services, sandboxed processes will "
"fail to start.", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 4878)
4877 "Failed to initialize broker services, sandboxed processes will "NS_DebugBreak(NS_DEBUG_WARNING, "Failed to initialize broker services, sandboxed processes will "
"fail to start.", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 4878)
4878 "fail to start.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to initialize broker services, sandboxed processes will "
"fail to start.", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 4878)
;
4879 }
4880#endif
4881
4882#ifdef XP_MACOSX
4883 // Set up ability to respond to system (Apple) events. This must occur before
4884 // ProcessUpdates to ensure that links clicked in external applications aren't
4885 // lost when updates are pending.
4886 SetupMacApplicationDelegate(&gRestartedByOS);
4887
4888 if (EnvHasValue("MOZ_LAUNCHED_CHILD")) {
4889 // Initialize the shared NSApplication early on relaunch so the dock
4890 // tile for the child process gets registered before the original
4891 // process exits. `[NSApplication sharedApplication]` calls
4892 // `_NSDoOneTimeDockRegistration` internally, which is enough.
4893 EnsureUseCocoaDockAPI();
4894 }
4895
4896 if (CheckArg("foreground")) {
4897 // The original process communicates that it was in the foreground by
4898 // adding this argument. This new process, which is taking over for
4899 // the old one, should make itself the active application.
4900 ProcessSerialNumber psn;
4901 if (::GetCurrentProcess(&psn) == noErr) {
4902 ::SetFrontProcess(&psn);
4903 }
4904 }
4905#endif
4906
4907 SaveToEnv("MOZ_LAUNCHED_CHILD=");
4908
4909 // On Windows, the -os-restarted command line switch lets us know when we are
4910 // restarted via RegisterApplicationRestart. May be used for other OSes later.
4911 if (CheckArg("os-restarted", nullptr, CheckArgFlag::RemoveArg) == ARG_FOUND) {
4912 gRestartedByOS = true;
4913 }
4914
4915 gRestartArgc = gArgc;
4916 gRestartArgv =
4917 (char**)malloc(sizeof(char*) * (gArgc + 1 + (override ? 2 : 0)));
4918 if (!gRestartArgv) {
4919 return 1;
4920 }
4921
4922 int i;
4923 for (i = 0; i < gArgc; ++i) {
4924 gRestartArgv[i] = gArgv[i];
4925 }
4926
4927 // Add the -override argument back (it is removed automatically be CheckArg)
4928 // if there is one
4929 if (override) {
4930 gRestartArgv[gRestartArgc++] = const_cast<char*>("-override");
4931 gRestartArgv[gRestartArgc++] = const_cast<char*>(override);
4932 }
4933
4934 gRestartArgv[gRestartArgc] = nullptr;
4935
4936 Maybe<bool> safeModeRequested = IsSafeModeRequested(gArgc, gArgv);
4937 if (!safeModeRequested) {
4938 return 1;
4939 }
4940#ifdef MOZ_BACKGROUNDTASKS1
4941 if (BackgroundTasks::IsBackgroundTaskMode()) {
4942 safeModeRequested = Some(false);
4943
4944 // Remove the --backgroundtask arg now that it has been saved in
4945 // gRestartArgv.
4946 const char* tmpBackgroundTaskName = nullptr;
4947 (void)CheckArg("backgroundtask", &tmpBackgroundTaskName,
4948 CheckArgFlag::RemoveArg);
4949 }
4950#endif
4951
4952 gSafeMode = safeModeRequested.value();
4953
4954 MaybeAddCPUMicrocodeCrashAnnotation();
4955 CrashReporter::RegisterAnnotationBool(CrashReporter::Annotation::SafeMode,
4956 &gSafeMode);
4957
4958 // Strip the now unsupported no-remote command line argument.
4959 CheckArg("no-remote");
4960
4961#if defined(MOZ_HAS_REMOTE1)
4962 // Handle the --new-instance command line arguments.
4963 ar = CheckArg("new-instance");
4964 if (ar == ARG_FOUND || EnvHasValue("MOZ_NEW_INSTANCE")) {
4965 mDisableRemoteClient = true;
4966 }
4967#else
4968 // These arguments do nothing in platforms with no remoting support but we
4969 // should remove them from the command line anyway.
4970 CheckArg("new-instance");
4971#endif
4972
4973#ifndef XP_WIN
4974 // This command line argument is only implemented on Windows. It should be
4975 // removed from the command line if present on other platforms.
4976 CheckArg("wait-for-browser");
4977#endif
4978
4979 ar = CheckArg("offline");
4980 if (ar || EnvHasValue("XRE_START_OFFLINE")) {
4981 mStartOffline = true;
4982 }
4983
4984 const char* origin = nullptr;
4985 if (!PR_GetEnv("MOZ_FORCE_QUIC_ON") &&
4986 ARG_FOUND == CheckArg("origin-to-force-quic-on", &origin,
4987 CheckArgFlag::RemoveArg)) {
4988 mOriginToForceQUIC.Assign(origin);
4989 }
4990
4991 // Handle --help command line argument.
4992 // It should return rather quickly, so we deal with it here.
4993 // Note: we *cannot* handle the argument as early as --*version because it
4994 // requires ScopedXPCOMStartup and other components be registered.
4995 if (CheckArg("h") || CheckArg("help") || CheckArg("?")) {
4996 DumpHelp();
4997 *aExitFlag = true;
4998 return 0;
4999 }
5000
5001#ifdef MOZ_ENABLE_DBUS1
5002 const char* dbusServiceLauncher = nullptr;
5003 ar = CheckArg("dbus-service", &dbusServiceLauncher, CheckArgFlag::None);
5004 if (ar == ARG_BAD) {
5005 Output(true, "Missing launcher param for --dbus-service\n");
5006 return 1;
5007 }
5008 if (ar == ARG_FOUND) {
5009 UniquePtr<DBusService> dbusService =
5010 MakeUnique<DBusService>(dbusServiceLauncher);
5011 if (dbusService->Init()) {
5012 dbusService->Run();
5013 }
5014 *aExitFlag = true;
5015 return 0;
5016 }
5017
5018# ifdef MOZ_WIDGET_GTK1
5019 if (XRE_IsParentProcess()) {
5020 widget::RegisterHostApp();
5021 }
5022# endif
5023#endif
5024
5025 rv = XRE_InitCommandLine(gArgc, gArgv);
5026 NS_ENSURE_SUCCESS(rv, 1)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5026); return 1; } } while (false)
;
5027
5028 return 0;
5029}
5030
5031#if defined(XP_LINUX1) && !defined(ANDROID)
5032
5033static void AnnotateLSBRelease(void*) {
5034 nsCString dist, desc, release, codename;
5035 if (widget::lsb::GetLSBRelease(dist, desc, release, codename)) {
5036 CrashReporter::AppendAppNotesToCrashReport(desc);
5037 }
5038}
5039
5040#endif // defined(XP_LINUX) && !defined(ANDROID)
5041
5042#ifdef XP_WIN
5043static void ReadAheadSystemDll(const wchar_t* dllName) {
5044 wchar_t dllPath[MAX_PATH];
5045 if (ConstructSystem32Path(dllName, dllPath, MAX_PATH)) {
5046 ReadAheadLib(dllPath);
5047 }
5048}
5049
5050static void ReadAheadPackagedDll(const wchar_t* dllName,
5051 const wchar_t* aGREDir) {
5052 wchar_t dllPath[MAX_PATH];
5053 swprintf(dllPath, MAX_PATH, L"%s\\%s", aGREDir, dllName);
5054 ReadAheadLib(dllPath);
5055}
5056
5057static void ReadAheadDlls(const wchar_t* greDir) {
5058 // In Bug 1628903, we investigated which DLLs we should prefetch in
5059 // order to reduce disk I/O and improve startup on Windows machines.
5060 // Our ultimate goal is to measure the impact of these improvements on
5061 // retention (see Bug 1640087). Before we place this within a pref,
5062 // we should ensure this feature only ships to the nightly channel
5063 // and monitor results from that subset.
5064 if (greDir) {
5065 // Prefetch the DLLs shipped with firefox
5066 ReadAheadPackagedDll(L"libegl.dll", greDir);
5067 ReadAheadPackagedDll(L"libGLESv2.dll", greDir);
5068 ReadAheadPackagedDll(L"freebl3.dll", greDir);
5069 ReadAheadPackagedDll(L"softokn3.dll", greDir);
5070
5071 // Prefetch the system DLLs
5072 ReadAheadSystemDll(L"DWrite.dll");
5073 ReadAheadSystemDll(L"D3DCompiler_47.dll");
5074 } else {
5075 // Load DataExchange.dll and twinapi.appcore.dll for
5076 // nsWindow::EnableDragDrop
5077 ReadAheadSystemDll(L"DataExchange.dll");
5078 ReadAheadSystemDll(L"twinapi.appcore.dll");
5079
5080 // Load twinapi.dll for WindowsUIUtils::UpdateTabletModeState
5081 ReadAheadSystemDll(L"twinapi.dll");
5082
5083 // Load explorerframe.dll for WinTaskbar::Initialize
5084 ReadAheadSystemDll(L"ExplorerFrame.dll");
5085
5086 // Load WinTypes.dll for nsOSHelperAppService::GetApplicationDescription
5087 ReadAheadSystemDll(L"WinTypes.dll");
5088 }
5089}
5090#endif
5091
5092#if defined(MOZ_UPDATER1) && !defined(MOZ_WIDGET_ANDROID)
5093enum struct ShouldNotProcessUpdatesReason {
5094 DevToolsLaunching,
5095 NotAnUpdatingTask,
5096 OtherInstanceRunning,
5097 FirstStartup,
5098 DisabledByEnvironment
5099};
5100
5101const char* ShouldNotProcessUpdatesReasonAsString(
5102 ShouldNotProcessUpdatesReason aReason) {
5103 switch (aReason) {
5104 case ShouldNotProcessUpdatesReason::DevToolsLaunching:
5105 return "DevToolsLaunching";
5106 case ShouldNotProcessUpdatesReason::NotAnUpdatingTask:
5107 return "NotAnUpdatingTask";
5108 case ShouldNotProcessUpdatesReason::OtherInstanceRunning:
5109 return "OtherInstanceRunning";
5110 case ShouldNotProcessUpdatesReason::DisabledByEnvironment:
5111 return "DisabledByEnvironment";
5112 default:
5113 MOZ_CRASH("impossible value for ShouldNotProcessUpdatesReason")do { do { } while (false); MOZ_ReportCrash("" "impossible value for ShouldNotProcessUpdatesReason"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 5113); AnnotateMozCrashReason
("MOZ_CRASH(" "impossible value for ShouldNotProcessUpdatesReason"
")"); do { MOZ_CrashSequence(__null, 5113); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
5114 }
5115}
5116
5117Maybe<ShouldNotProcessUpdatesReason> ShouldNotProcessUpdates(
5118 nsXREDirProvider& aDirProvider) {
5119 // Don't process updates when launched from the installer.
5120 // It's possible for a stale update to be present in the case of a paveover;
5121 // ignore it and leave the update service to discard it.
5122 if (ARG_FOUND == CheckArgExists("first-startup")) {
5123 NS_WARNING("ShouldNotProcessUpdates(): FirstStartup")NS_DebugBreak(NS_DEBUG_WARNING, "ShouldNotProcessUpdates(): FirstStartup"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5123)
;
5124 return Some(ShouldNotProcessUpdatesReason::FirstStartup);
5125 }
5126
5127 // Bug 2055849: Don't process updates if MOZ_DISABLE_UPDATE_PROCESSING is set.
5128 // Set by default when using https://github.com/mozilla/firefox-devtools-mcp.
5129 if (EnvHasValue("MOZ_DISABLE_UPDATE_PROCESSING")) {
5130 NS_WARNING("ShouldNotProcessUpdates(): DisabledByEnvironment")NS_DebugBreak(NS_DEBUG_WARNING, "ShouldNotProcessUpdates(): DisabledByEnvironment"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5130)
;
5131 return Some(ShouldNotProcessUpdatesReason::DisabledByEnvironment);
5132 }
5133
5134 // Do not process updates if we're launching devtools, as evidenced by
5135 // "--chrome ..." with the browser toolbox chrome document URL.
5136
5137 // Keep this synchronized with the value of the same name in
5138 // devtools/client/framework/browser-toolbox/Launcher.sys.mjs. Or, for bonus
5139 // points, lift this value to nsIXulRuntime or similar, so that it can be
5140 // accessed in both locations. (The prefs service isn't available at this
5141 // point so the simplest manner of sharing the value is not available to us.)
5142 const char* BROWSER_TOOLBOX_WINDOW_URL =
5143 "chrome://devtools/content/framework/browser-toolbox/window.html";
5144
5145 const char* chromeParam = nullptr;
5146 if (ARG_FOUND == CheckArg("chrome", &chromeParam, CheckArgFlag::None)) {
5147 if (!chromeParam || !strcmp(BROWSER_TOOLBOX_WINDOW_URL, chromeParam)) {
5148 NS_WARNING("ShouldNotProcessUpdates(): DevToolsLaunching")NS_DebugBreak(NS_DEBUG_WARNING, "ShouldNotProcessUpdates(): DevToolsLaunching"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5148)
;
5149 return Some(ShouldNotProcessUpdatesReason::DevToolsLaunching);
5150 }
5151 }
5152
5153# ifdef MOZ_BACKGROUNDTASKS1
5154 // Do not process updates if we're running a background task mode and another
5155 // instance is already running. This avoids periodic maintenance updating
5156 // underneath a browsing session.
5157 Maybe<nsCString> backgroundTasks = BackgroundTasks::GetBackgroundTasks();
5158 if (backgroundTasks.isSome()) {
5159 // Only process updates for specific tasks: at this time, the
5160 // `backgroundupdate` task and the test-only `shouldprocessupdates` task.
5161 //
5162 // Background tasks can be sparked by Firefox instances that are shutting
5163 // down, which can cause races between the task startup trying to update and
5164 // Firefox trying to invoke the updater. This happened when converting
5165 // `pingsender` to a background task, since it is launched to send pings at
5166 // shutdown: Bug 1736373.
5167 //
5168 // We'd prefer to have this be a property of the task definition sibling to
5169 // `backgroundTaskTimeoutSec`, but when we reach this code we're well before
5170 // we can load the task JSM.
5171 if (!BackgroundTasks::IsUpdatingTaskName(backgroundTasks.ref())) {
5172 NS_WARNING("ShouldNotProcessUpdates(): NotAnUpdatingTask")NS_DebugBreak(NS_DEBUG_WARNING, "ShouldNotProcessUpdates(): NotAnUpdatingTask"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5172)
;
5173 return Some(ShouldNotProcessUpdatesReason::NotAnUpdatingTask);
5174 }
5175
5176 // At this point we have a dir provider but no XPCOM directory service. We
5177 // launch the update sync manager using that information so that it doesn't
5178 // need to ask for (and fail to find) the directory service.
5179 nsCOMPtr<nsIFile> anAppFile;
5180 bool persistent;
5181 nsresult rv = aDirProvider.GetFile(XRE_EXECUTABLE_FILE"XREExeF", &persistent,
5182 getter_AddRefs(anAppFile));
5183 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !anAppFile) {
5184 // Strange, but not a reason to skip processing updates.
5185 return Nothing();
5186 }
5187
5188 auto updateSyncManager = new nsUpdateSyncManager(anAppFile);
5189
5190 bool otherInstance = false;
5191 updateSyncManager->IsOtherInstanceRunning(&otherInstance);
5192 if (otherInstance) {
5193 NS_WARNING("ShouldNotProcessUpdates(): OtherInstanceRunning")NS_DebugBreak(NS_DEBUG_WARNING, "ShouldNotProcessUpdates(): OtherInstanceRunning"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5193)
;
5194 return Some(ShouldNotProcessUpdatesReason::OtherInstanceRunning);
5195 }
5196 }
5197# endif
5198
5199 return Nothing();
5200}
5201#endif
5202
5203namespace mozilla::startup {
5204Result<nsCOMPtr<nsIFile>, nsresult> GetIncompleteStartupFile(nsIFile* aProfLD) {
5205 nsCOMPtr<nsIFile> crashFile;
5206 MOZ_TRY(aProfLD->Clone(getter_AddRefs(crashFile)))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(aProfLD->Clone(getter_AddRefs(crashFile))); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
5207 MOZ_TRY(crashFile->Append(FILE_STARTUP_INCOMPLETE))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(crashFile->Append(u".startup-incomplete"_ns)); if ((__builtin_expect
(!!(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
5208 return std::move(crashFile);
5209}
5210} // namespace mozilla::startup
5211
5212// Check whether the last startup attempt resulted in a crash or hang.
5213// This is distinct from the definition of a startup crash from
5214// nsAppStartup::TrackStartupCrashBegin.
5215bool XREMain::CheckLastStartupWasCrash() {
5216 Result<nsCOMPtr<nsIFile>, nsresult> crashFile =
5217 GetIncompleteStartupFile(mProfLD);
5218 if (crashFile.isErr()) {
5219 return true;
5220 }
5221
5222 // Attempt to create the incomplete startup canary file. If the file already
5223 // exists, this fails, and we know the last startup was a crash. If it
5224 // doesn't already exist, it is created, and will be removed at the end of
5225 // the startup crash detection window.
5226 AutoFDClose fd;
5227 (void)crashFile.inspect()->OpenNSPRFileDesc(
5228 PR_WRONLY0x02 | PR_CREATE_FILE0x08 | PR_EXCL0x80, 0666, getter_Transfers(fd));
5229 return !fd;
5230}
5231
5232/*
5233 * XRE_mainStartup - Initializes the profile and various other services.
5234 * Main() will exit early if either return value != 0 or if aExitFlag is
5235 * true.
5236 */
5237int XREMain::XRE_mainStartup(bool* aExitFlag) {
5238 nsresult rv;
5239
5240 if (!aExitFlag) return 1;
5241 *aExitFlag = false;
5242
5243#ifdef XP_MACOSX
5244 mozilla::MacAutoreleasePool pool;
5245#endif
5246
5247 // Enable Telemetry IO Reporting on DEBUG, nightly and local builds,
5248 // but disable it on FUZZING builds and for ANDROID.
5249#ifndef FUZZING
5250# ifndef ANDROID
5251# ifdef DEBUG1
5252 mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
5253# else
5254 {
5255 const char* releaseChannel = MOZ_STRINGIFY(MOZ_UPDATE_CHANNEL)"default";
5256 if (strcmp(releaseChannel, "nightly") == 0 ||
5257 strcmp(releaseChannel, "default") == 0) {
5258 mozilla::Telemetry::InitIOReporting(gAppData->xreDirectory);
5259 }
5260 }
5261# endif /* DEBUG */
5262# endif /* ANDROID */
5263#endif /* FUZZING */
5264
5265#if defined(XP_WIN)
5266 // Enable the HeapEnableTerminationOnCorruption exploit mitigation. We ignore
5267 // the return code because it always returns success, although it has no
5268 // effect on Windows older than XP SP3.
5269 HeapSetInformation(NULL__null, HeapEnableTerminationOnCorruption, NULL__null, 0);
5270#endif /* XP_WIN */
5271
5272#ifdef MOZ_WIDGET_GTK1
5273 // Stash startup token in owned memory because gtk_init will clear
5274 // DESKTOP_STARTUP_ID it.
5275 if (const char* v = PR_GetEnv("DESKTOP_STARTUP_ID")) {
5276 mDesktopStartupID.Assign(v);
5277 }
5278 if (const char* v = PR_GetEnv("XDG_ACTIVATION_TOKEN")) {
5279 mXDGActivationToken.Assign(v);
5280 }
5281#endif
5282
5283#if defined(XP_WIN)
5284 {
5285 // Save the shortcut path before lpTitle is replaced by an AUMID,
5286 // such as by WinTaskbar
5287 STARTUPINFOW si;
5288 GetStartupInfoW(&si);
5289 if (si.dwFlags & STARTF_TITLEISAPPID) {
5290 NS_WARNING("AUMID was already set, shortcut may have been lost.")NS_DebugBreak(NS_DEBUG_WARNING, "AUMID was already set, shortcut may have been lost."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5290)
;
5291 } else if ((si.dwFlags & STARTF_TITLEISLINKNAME) && si.lpTitle) {
5292 gProcessStartupShortcut.Assign(si.lpTitle);
5293 }
5294 }
5295#endif /* XP_WIN */
5296
5297#if defined(MOZ_WIDGET_GTK1)
5298 // setup for private colormap. Ideally we'd like to do this
5299 // in nsAppShell::Create, but we need to get in before gtk
5300 // has been initialized to make sure everything is running
5301 // consistently.
5302
5303 // Set program name to the one defined in application.ini.
5304 g_set_prgname(gAppData->remotingName);
5305
5306 // Initialize GTK here for splash.
5307
5308# if defined(MOZ_X111)
5309 // Disable XInput2 multidevice support due to focus bugginess.
5310 // See bugs 1182700, 1170342.
5311 // gdk_disable_multidevice() affects Gdk X11 backend only,
5312 // the multidevice support is always enabled on Wayland backend.
5313 int32_t useXI2 = 0;
5314 if (const char* useXI2Env = PR_GetEnv("MOZ_USE_XINPUT2")) {
5315 useXI2 = (*useXI2Env != '0');
5316 } else {
5317 // Steam Deck needs multidevice support for touchscreen
5318 if (const char* currentDesktop = PR_GetEnv("XDG_CURRENT_DESKTOP")) {
5319 useXI2 |= (nsDependentCString(currentDesktop) == "gamescope"_ns);
5320 }
5321# ifdef EARLY_BETA_OR_EARLIER1
5322 // We tried 3.24.0+ but had problems, let's retry with newer versions. See
5323 // bug 1660212.
5324 useXI2 |= !gtk_check_version(3, 24, 49);
5325# endif
5326 }
5327 if (!useXI2) {
5328 gdk_disable_multidevice();
5329 }
5330# endif /* MOZ_X11 */
5331
5332 // Open the display ourselves instead of using gtk_init, so that we can
5333 // close it without fear that one day gtk might clean up the display it
5334 // opens.
5335 if (!gtk_parse_args(&gArgc, &gArgv)) return 1;
5336#endif /* MOZ_WIDGET_GTK */
5337
5338#ifdef FUZZING
5339 if (PR_GetEnv("FUZZER")) {
5340 *aExitFlag = true;
5341 return mozilla::fuzzerRunner->Run(&gArgc, &gArgv);
5342 }
5343#endif
5344
5345 if (PR_GetEnv("MOZ_RUN_GTEST")) {
5346 int result;
5347#ifdef XP_WIN
5348 UseParentConsole();
5349#endif
5350 // RunGTest will only be set if we're in xul-unit
5351 if (mozilla::RunGTest) {
5352 gIsGtest = true;
5353 result = mozilla::RunGTest(&gArgc, gArgv);
5354 gIsGtest = false;
5355 } else {
5356 result = 1;
5357 printf("TEST-UNEXPECTED-FAIL | gtest | Not compiled with enable-tests\n");
5358 }
5359 *aExitFlag = true;
5360 return result;
5361 }
5362
5363 bool isBackgroundTaskMode = false;
5364#ifdef MOZ_BACKGROUNDTASKS1
5365 isBackgroundTaskMode = BackgroundTasks::IsBackgroundTaskMode();
5366#endif
5367
5368#ifdef MOZ_HAS_REMOTE1
5369 if (gfxPlatform::IsHeadless()) {
5370 mDisableRemoteClient = true;
5371 }
5372#endif
5373
5374#ifdef MOZ_X111
5375 // Init X11 in thread-safe mode. Must be called prior to the first call to
5376 // XOpenDisplay (called inside gdk_display_open). This is a requirement for
5377 // off main tread compositing.
5378 if (!isBackgroundTaskMode && !gfxPlatform::IsHeadless()) {
5379 XInitThreads();
5380 }
5381#endif
5382#if defined(MOZ_WIDGET_GTK1)
5383 if (!isBackgroundTaskMode && !gfxPlatform::IsHeadless()) {
5384 const char* display_name = nullptr;
5385 bool saveDisplayArg = false;
5386
5387 // display_name is owned by gdk.
5388 display_name = gdk_get_display_arg_name();
5389 bool waylandEnabled = IsWaylandEnabled();
5390# ifdef MOZ_WAYLAND1
5391 if (!display_name) {
5392 auto* proxyEnv = getenv("MOZ_DISABLE_WAYLAND_PROXY");
5393 bool disableWaylandProxy = proxyEnv && *proxyEnv;
5394 if (!disableWaylandProxy && XRE_IsParentProcess() && waylandEnabled) {
5395 auto* proxyLog = getenv("WAYLAND_PROXY_LOG");
5396 WaylandProxy::SetVerbose(proxyLog && *proxyLog);
5397
5398# ifdef NIGHTLY_BUILD1
5399 bool captureProtocolErrors = true;
5400# else
5401 bool captureProtocolErrors = false;
5402# endif
5403 // MOZ_WAYLAND_PROTOCOL_ERROR_DETAILS=0 turns capture off on Nightly;
5404 // any other non-empty value turns it on elsewhere.
5405 if (auto* errorDetails = getenv("MOZ_WAYLAND_PROTOCOL_ERROR_DETAILS")) {
5406 captureProtocolErrors = *errorDetails && *errorDetails != '0';
5407 }
5408 WaylandProxy::SetCaptureProtocolErrors(captureProtocolErrors);
5409
5410 WaylandProxy::SetThreadStartCallback(
5411 [] { PROFILER_REGISTER_THREAD("WaylandProxy")do { char stackTop; profiler_register_thread("WaylandProxy", &
stackTop); } while (0)
; });
5412 WaylandProxy::SetThreadStopCallback(
5413 [] { PROFILER_UNREGISTER_THREAD()profiler_unregister_thread(); });
5414 WaylandProxy::SetCompositorUnavailableHandler(
5415 WlCompositorUnavailableHandler);
5416 WaylandProxy::SetCompositorSilentDisconnectHandler(
5417 WlCompositorSilentDisconnectHandler);
5418 WaylandProxy::AddState(WAYLAND_PROXY_ENABLED(1 << 0));
5419 gWaylandProxy = WaylandProxy::Create();
5420 if (gWaylandProxy) {
5421 if (!gWaylandProxy->RunThread()) {
5422 Output(true, "Failed to run Wayland proxy\n");
5423 }
5424 }
5425 } else {
5426 WaylandProxy::AddState(WAYLAND_PROXY_DISABLED(1 << 1));
5427 }
5428 }
5429# endif
5430
5431 // if --display argument is given make sure it's
5432 // also passed to ContentChild::Init() by MOZ_GDK_DISPLAY.
5433 if (display_name) {
5434 SaveWordToEnv("MOZ_GDK_DISPLAY", nsDependentCString(display_name));
5435 saveDisplayArg = true;
5436 }
5437
5438 // On Wayland disabled builds read X11 DISPLAY env exclusively
5439 // and don't care about different displays.
5440 if (!waylandEnabled && !display_name) {
5441 display_name = PR_GetEnv("DISPLAY");
5442 if (!display_name) {
5443 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
5444 "Error: no DISPLAY environment variable specified\n");
5445 return 1;
5446 }
5447 }
5448
5449 if (display_name) {
5450 GdkDisplay* disp = gdk_display_open(display_name);
5451 if (!disp) {
5452 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Error: cannot open display: %s\n", display_name);
5453 return 1;
5454 }
5455 if (saveDisplayArg) {
5456 if (GdkIsX11Display(disp)) {
5457 SaveWordToEnv("DISPLAY", nsDependentCString(display_name));
5458 } else if (GdkIsWaylandDisplay(disp)) {
5459 SaveWordToEnv("WAYLAND_DISPLAY", nsDependentCString(display_name));
5460 }
5461 }
5462 } else {
5463 gdk_display_manager_open_display(gdk_display_manager_get(), nullptr);
5464 }
5465# if defined(MOZ_WAYLAND1)
5466 // We want to use proxy for main connection only so
5467 // restore original Wayland display for next potential Wayland connections
5468 // from gfx probe code and so on.
5469 if (gWaylandProxy) {
5470 gWaylandProxy->RestoreWaylandDisplay();
5471 }
5472 if (waylandEnabled && PR_GetEnv("WAYLAND_DISPLAY") && GdkIsX11Display()) {
5473 // Gtk somehow switched to X11 display but we want Wayland.
5474 // It may happen if compositor response is missig or it's slow
5475 // or WAYLAND_DISPLAY is wrong. In such case throw warning but
5476 // run with X11.
5477 Output(true,
5478 "Error: Failed to open Wayland display, fallback to X11. "
5479 "WAYLAND_DISPLAY='%s' DISPLAY='%s'\n",
5480 PR_GetEnv("WAYLAND_DISPLAY"), PR_GetEnv("DISPLAY"));
5481
5482 // We need to unset WAYLAND_DISPLAY. Gfx probe code doesn't have fallback
5483 // to X11 and we'll end with Browser running SW rendering only then.
5484 g_unsetenv("WAYLAND_DISPLAY");
5485 gWaylandProxy = nullptr;
5486 }
5487# endif
5488 if (!gdk_display_get_default()) {
5489 Output(true,
5490 "Error: we don't have any display, WAYLAND_DISPLAY='%s' "
5491 "DISPLAY='%s'\n",
5492 PR_GetEnv("WAYLAND_DISPLAY"), PR_GetEnv("DISPLAY"));
5493 return 1;
5494 }
5495 // Check that Wayland only and X11 only builds
5496 // use appropriate displays.
5497# if defined(MOZ_WAYLAND1) && !defined(MOZ_X111)
5498 if (!GdkIsWaylandDisplay()) {
5499 Output(true, "Wayland only build is missig Wayland display!\n");
5500 return 1;
5501 }
5502# endif
5503# if !defined(MOZ_WAYLAND1) && defined(MOZ_X111)
5504 if (!GdkIsX11Display()) {
5505 Output(true, "X11 only build is missig X11 display!\n");
5506 return 1;
5507 }
5508# endif
5509 }
5510#endif
5511#if defined(MOZ_HAS_REMOTE1)
5512 // handle --remote now that xpcom is fired up
5513 gRemoteService = new nsRemoteService();
5514 if (gRemoteService) {
5515 gRemoteService->SetProgram(gAppData->remotingName);
5516 gStartupLock = gRemoteService->LockStartup();
5517 if (!gStartupLock) {
5518 NS_WARNING("Failed to lock for startup, continuing anyway.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to lock for startup, continuing anyway."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5518)
;
5519 }
5520 }
5521#endif
5522#if defined(MOZ_WIDGET_GTK1)
5523 g_set_application_name(mAppData->name);
5524
5525#endif /* defined(MOZ_WIDGET_GTK) */
5526#ifdef MOZ_X111
5527 // Do this after initializing GDK, or GDK will install its own handler.
5528 XRE_InstallX11ErrorHandler();
5529#endif
5530
5531 bool canRun = false;
5532 rv = mNativeApp->Start(&canRun);
5533 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0))) || !canRun) {
5534 return 1;
5535 }
5536
5537#ifdef MOZ_WIDGET_GTK1
5538 // startup token might be cleared now, we recover it in case we need a
5539 // restart.
5540 if (!mDesktopStartupID.IsEmpty()) {
5541 // Leak it with extreme prejudice!
5542 PR_SetEnv(ToNewCString("DESKTOP_STARTUP_ID="_ns + mDesktopStartupID));
5543 }
5544
5545 if (!mXDGActivationToken.IsEmpty()) {
5546 // Leak it with extreme prejudice!
5547 PR_SetEnv(ToNewCString("XDG_ACTIVATION_TOKEN="_ns + mXDGActivationToken));
5548 }
5549#endif
5550
5551 // Support exiting early for testing startup sequence. Bug 1360493
5552 if (CheckArg("test-launch-without-hang")) {
5553 *aExitFlag = true;
5554 return 0;
5555 }
5556
5557 mProfileSvc = NS_GetToolkitProfileService();
5558 if (!mProfileSvc) {
5559 // We failed to choose or create profile - notify user and quit
5560 ProfileMissingDialog(mNativeApp);
5561 return 1;
5562 }
5563
5564 bool wasDefaultSelection;
5565 nsCOMPtr<nsIToolkitProfile> profile;
5566 RefPtr profileSvc = mProfileSvc;
5567 nsCOMPtr nativeApp = mNativeApp;
5568 rv = SelectProfile(profileSvc, nativeApp, getter_AddRefs(mProfD),
5569 getter_AddRefs(mProfLD), getter_AddRefs(profile),
5570 &wasDefaultSelection);
5571 if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
5572 *aExitFlag = true;
5573 return 0;
5574 }
5575
5576 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5577 // We failed to choose or create profile - notify user and quit
5578 ProfileMissingDialog(mNativeApp);
5579 return 1;
5580 }
5581
5582#if defined(MOZ_HAS_REMOTE1)
5583 if (gRemoteService) {
5584 // Use the full profile path to identify the profile.
5585 nsCString profilePath;
5586
5587# ifdef XP_WIN
5588 nsString path;
5589 rv = mProfD->GetPath(path);
5590 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5591 CopyUTF16toUTF8(path, profilePath);
5592 }
5593# else
5594 rv = mProfD->GetNativePath(profilePath);
5595# endif
5596
5597 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5598 gRemoteService->SetProfile(profilePath);
5599
5600 if (!mDisableRemoteClient) {
5601 // Try to remote the entire command line. If this fails, start up
5602 // normally.
5603# ifdef MOZ_WIDGET_GTK1
5604 auto& startupToken =
5605 GdkIsWaylandDisplay() ? mXDGActivationToken : mDesktopStartupID;
5606# ifdef MOZ_X111
5607 if (GdkIsX11Display() && startupToken.IsEmpty()) {
5608 startupToken = SynthesizeStartupToken();
5609 }
5610# endif /* MOZ_X11 */
5611 gRemoteService->SetStartupToken(startupToken);
5612# endif
5613 rv = gRemoteService->StartClient();
5614
5615 if (rv == NS_ERROR_NOT_AVAILABLE && profile) {
5616 // Older versions would use the profile name in preference to the
5617 // path.
5618 nsCString profileName;
5619 profile->GetName(profileName);
5620 gRemoteService->SetProfile(profileName);
5621
5622 rv = gRemoteService->StartClient();
5623
5624 // Reset back to the path.
5625 gRemoteService->SetProfile(profilePath);
5626 }
5627
5628 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5629 *aExitFlag = true;
5630 gStartupLock = nullptr;
5631 return 0;
5632 }
5633
5634 if (rv == NS_ERROR_INVALID_ARG) {
5635 gStartupLock = nullptr;
5636 return 1;
5637 }
5638 }
5639 }
5640 }
5641#endif /* MOZ_HAS_REMOTE */
5642
5643#if defined(MOZ_UPDATER1) && !defined(MOZ_WIDGET_ANDROID)
5644# ifdef XP_WIN
5645 {
5646 // When automatically restarting for a staged background update
5647 // we want the child process to wait here so that the updater
5648 // does not register two instances running and use that as a
5649 // reason to not process updates. This function requires having
5650 // -restart-pid <param> in the command line to function properly.
5651 // Ensure we keep -restart-pid if we are running tests
5652 if (ARG_FOUND == CheckArgExists("restart-pid") &&
5653 !CheckArg("test-only-automatic-restart-no-wait")) {
5654 // We're not testing and can safely remove it now and read the pid.
5655 const char* restartPidString = nullptr;
5656 CheckArg("restart-pid", &restartPidString, CheckArgFlag::RemoveArg);
5657 // pid should be first parameter following -restart-pid.
5658 uint32_t pid = nsDependentCString(restartPidString).ToInteger(&rv, 10U);
5659 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && pid > 0) {
5660 printf_stderr(
5661 "*** MaybeWaitForProcessExit: launched pidDWORD = %u ***\n", pid);
5662 RefPtr<nsUpdateProcessor> updater = new nsUpdateProcessor();
5663 rv = updater->WaitForProcessExit(pid, MAYBE_WAIT_TIMEOUT_MS);
5664 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5665 NS_WARNING("Failure in nsUpdateProcessor::WaitForProcessExit.")NS_DebugBreak(NS_DEBUG_WARNING, "Failure in nsUpdateProcessor::WaitForProcessExit."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5665)
;
5666 }
5667 } else {
5668 NS_WARNING("Failed to parse pid from -restart-pid.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to parse pid from -restart-pid."
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
5668)
;
5669 }
5670 }
5671 }
5672# endif
5673 // Check for and process any available updates
5674 nsCOMPtr<nsIFile> updRoot;
5675 bool persistent;
5676 rv = mDirProvider.GetFile(XRE_UPDATE_ROOT_DIR"UpdRootD", &persistent,
5677 getter_AddRefs(updRoot));
5678 // XRE_UPDATE_ROOT_DIR may fail. Fallback to appDir if failed
5679 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5680 updRoot = mDirProvider.GetAppDir();
5681 }
5682
5683 Maybe<ShouldNotProcessUpdatesReason> shouldNotProcessUpdatesReason =
5684 ShouldNotProcessUpdates(mDirProvider);
5685 if (shouldNotProcessUpdatesReason.isNothing()) {
5686 nsCOMPtr<nsIFile> exeFile, exeDir;
5687 rv = mDirProvider.GetFile(XRE_EXECUTABLE_FILE"XREExeF", &persistent,
5688 getter_AddRefs(exeFile));
5689 NS_ENSURE_SUCCESS(rv, 1)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5689); return 1; } } while (false)
;
5690 rv = exeFile->GetParent(getter_AddRefs(exeDir));
5691 NS_ENSURE_SUCCESS(rv, 1)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5691); return 1; } } while (false)
;
5692 ProcessUpdates(mDirProvider.GetGREDir(), exeDir, updRoot, gRestartArgc,
5693 gRestartArgv, mAppData->version);
5694 } else {
5695 if (CheckArg("test-should-not-process-updates") ||
5696 EnvHasValue("MOZ_TEST_SHOULD_NOT_PROCESS_UPDATES")) {
5697 // Support for testing *not* processing an update. The launched process
5698 // can witness this environment variable and conclude that its runtime
5699 // environment resulted in not processing updates.
5700
5701 SaveToEnv(nsPrintfCString("MOZ_TEST_SHOULD_NOT_PROCESS_UPDATES="
5702 "ShouldNotProcessUpdates(): %s",
5703 ShouldNotProcessUpdatesReasonAsString(
5704 shouldNotProcessUpdatesReason.value()))
5705 .get());
5706 }
5707 }
5708 if (CheckArg("test-process-updates") ||
5709 EnvHasValue("MOZ_TEST_PROCESS_UPDATES")) {
5710 SaveToEnv("MOZ_TEST_PROCESS_UPDATES=");
5711
5712 // If the caller has asked us to log our arguments, do so. This is used
5713 // to make sure that the maintenance service successfully launches the
5714 // callback application.
5715 const char* logFile = nullptr;
5716 if (ARG_FOUND == CheckArg("dump-args", &logFile)) {
5717 FILE* logFP = fopen(logFile, "wb");
5718 if (logFP) {
5719 for (int i = 1; i < gRestartArgc; ++i) {
5720 fprintf(logFP, "%s\n", gRestartArgv[i]);
5721 }
5722 fclose(logFP);
5723 }
5724 }
5725
5726 // Tests may want to know when we are done. We are about to exit, so we are
5727 // done here. Write out a file to indicate this to the caller.
5728 WriteUpdateCompleteTestFile(updRoot);
5729
5730 *aExitFlag = true;
5731 return 0;
5732 }
5733#endif
5734
5735 // We now know there is no existing instance using the selected profile.
5736
5737 // We only ever show the profile selector if a specific profile wasn't chosen
5738 // via command line arguments or environment variables.
5739 if (wasDefaultSelection) {
5740 if (ShouldSkipProfileDialogForWebAuth()) {
5741 rv = NS_OK;
5742 } else if (!mProfileSvc->GetStartWithLastProfile()) {
5743 // First check the old style profile manager
5744 rv = ShowProfileManager(profileSvc, nativeApp);
5745 } else if (profile && profile->GetShowProfileSelector()) {
5746 // Now check the new profile group selector
5747 rv = ShowProfileSelector(profileSvc, nativeApp);
5748 } else {
5749 rv = NS_OK;
5750 }
5751
5752 if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
5753 *aExitFlag = true;
5754 return 0;
5755 }
5756
5757 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5758 return 1;
5759 }
5760 }
5761
5762 // We always want to lock the profile even if we're actually going to reset
5763 // it later.
5764 rv = LockProfile(mNativeApp, mProfD, mProfLD, profile,
5765 getter_AddRefs(mProfileLock));
5766 if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
5767 *aExitFlag = true;
5768 return 0;
5769 }
5770 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5771 return 1;
5772 }
5773
5774 if (gDoProfileReset) {
5775 if (!EnvHasValue("MOZ_RESET_PROFILE_RESTART")) {
5776 if (ARG_FOUND == CheckArgExists("first-startup")) {
5777 // If the profile reset was initiated by the stub installer, we want to
5778 // set MOZ_RESET_PROFILE_SESSION so we can check for it later when the
5779 // Firefox Profile Migrator runs. At that point we set overrides to
5780 // ensure users see the right homepage.
5781 SaveToEnv("MOZ_RESET_PROFILE_SESSION=0");
5782 } else if (gDoMigration) {
5783 // Otherwise this is a profile reset and migration triggered via the
5784 // command line during development and we want to restore the session
5785 // and perform the approriate homepage overrides.
5786 SaveToEnv("MOZ_RESET_PROFILE_SESSION=1");
5787 }
5788 } else {
5789 // If the profile reset was initiated by the user, such as through
5790 // about:support, we want to restore their session.
5791 SaveToEnv("MOZ_RESET_PROFILE_SESSION=1");
5792 SaveToEnv("MOZ_RESET_PROFILE_RESTART=");
5793 }
5794 // Unlock the source profile.
5795 mProfileLock->Unlock();
5796
5797 // If we're resetting a profile, create a new one and use it to startup.
5798 gResetOldProfile = profile;
5799 rv = mProfileSvc->CreateResetProfile(getter_AddRefs(profile));
5800 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
5801 rv = profile->GetRootDir(getter_AddRefs(mProfD));
5802 NS_ENSURE_SUCCESS(rv, 1)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5802); return 1; } } while (false)
;
5803 SaveFileToEnv("XRE_PROFILE_PATH", mProfD);
5804
5805 rv = profile->GetLocalDir(getter_AddRefs(mProfLD));
5806 NS_ENSURE_SUCCESS(rv, 1)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5806); return 1; } } while (false)
;
5807 SaveFileToEnv("XRE_PROFILE_LOCAL_PATH", mProfLD);
5808
5809 // Lock the new profile
5810 rv = LockProfile(mNativeApp, mProfD, mProfLD, profile,
5811 getter_AddRefs(mProfileLock));
5812 if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
5813 *aExitFlag = true;
5814 return 0;
5815 }
5816 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
5817 return 1;
5818 }
5819 } else {
5820 NS_WARNING("Profile reset failed.")NS_DebugBreak(NS_DEBUG_WARNING, "Profile reset failed.", nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 5820)
;
5821 return 1;
5822 }
5823 }
5824
5825 gProfileLock = mProfileLock;
5826
5827 nsAutoCString version;
5828 BuildVersion(version);
5829
5830#ifdef TARGET_OS_ABI"Linux_x86_64-gcc3"
5831 constexpr auto osABI = nsLiteralCString{TARGET_OS_ABI"Linux_x86_64-gcc3"};
5832#else
5833 // No TARGET_XPCOM_ABI, but at least the OS is known
5834 constexpr auto osABI = nsLiteralCString{OS_TARGET"Linux" "_UNKNOWN"};
5835#endif
5836
5837 // Check for version compatibility with the last version of the app this
5838 // profile was started with. The format of the version stamp is defined
5839 // by the BuildVersion function.
5840 // Also check to see if something has happened to invalidate our
5841 // fastload caches, like an app upgrade.
5842
5843 // If we see .purgecaches, that means someone did a make.
5844 // Re-register components to catch potential changes.
5845 nsCOMPtr<nsIFile> flagFile;
5846 if (mAppData->directory) {
5847 (void)mAppData->directory->Clone(getter_AddRefs(flagFile));
5848 }
5849 if (flagFile) {
5850 flagFile->AppendNative(FILE_INVALIDATE_CACHES".purgecaches"_ns);
5851 }
5852
5853 CompatCheckResult compatResult =
5854 CheckCompatibility(mProfD, version, osABI, mDirProvider.GetGREDir(),
5855 mAppData->directory, flagFile);
5856
5857 bool cachesOK = compatResult.cachesOK;
5858
5859 gLastAppVersion = compatResult.lastAppVersion;
5860 gLastAppBuildID = compatResult.lastAppBuildID;
5861 gProfileEncryptedDatabases = compatResult.hasEncryptedDatabases;
5862
5863 MOZ_RELEASE_ASSERT(!cachesOK || compatResult.lastVersion.Equals(version),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!cachesOK || compatResult.lastVersion.Equals(version
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!cachesOK || compatResult.lastVersion.Equals(version
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!cachesOK || compatResult.lastVersion.Equals(version)" " ("
"Caches cannot be good if the version has changed." ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5864); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!cachesOK || compatResult.lastVersion.Equals(version)"
") (" "Caches cannot be good if the version has changed." ")"
); do { MOZ_CrashSequence(__null, 5864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
5864 "Caches cannot be good if the version has changed.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!cachesOK || compatResult.lastVersion.Equals(version
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!cachesOK || compatResult.lastVersion.Equals(version
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!cachesOK || compatResult.lastVersion.Equals(version)" " ("
"Caches cannot be good if the version has changed." ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5864); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "!cachesOK || compatResult.lastVersion.Equals(version)"
") (" "Caches cannot be good if the version has changed." ")"
); do { MOZ_CrashSequence(__null, 5864); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5865
5866 // Refuse to launch if the profile's on-disk encryption state and the
5867 // launching build's pref disagree: silently opening encrypted DBs with
5868 // the wrong VFS (or plaintext DBs as ciphertext) would corrupt them.
5869 // This must run before any storage code. Skip in backgroundtask mode:
5870 // those tasks operate on profile files independently of any SQLite
5871 // consumer and must succeed regardless of the gate.
5872#ifdef MOZ_BACKGROUNDTASKS1
5873 if (!BackgroundTasks::IsBackgroundTaskMode())
5874#endif
5875 {
5876 bool prefEnabled =
5877 StaticPrefs::security_storage_encryption_sqlite_enabled();
5878 EncryptionCompatResult ec =
5879 CheckEncryptionCompatibility(mProfD, prefEnabled);
5880 if (ec != EncryptionCompatResult::OK) {
5881 const char* msgKey =
5882 ec == EncryptionCompatResult::RefuseEncryptedButPrefOff
5883 ? "profileEncryptedButPrefOff"
5884 : "profileNotEncryptedButPrefOn";
5885 const char* titleKey =
5886 ec == EncryptionCompatResult::RefuseEncryptedButPrefOff
5887 ? "profileEncryptedButPrefOffTitle"
5888 : "profileNotEncryptedButPrefOnTitle";
5889 (void)ProfileEncryptionMismatchDialog(msgKey, titleKey, mNativeApp);
5890 *aExitFlag = true;
5891 return 0;
5892 }
5893 }
5894
5895#ifdef MOZ_BLOCK_PROFILE_DOWNGRADE1
5896 // The argument check must come first so the argument is always removed from
5897 // the command line regardless of whether this is a downgrade or not.
5898 if (!CheckArg("allow-downgrade") && compatResult.isDowngrade &&
5899 !EnvHasValue("MOZ_ALLOW_DOWNGRADE")) {
5900# ifdef XP_MACOSX
5901 InitializeMacApp();
5902# endif
5903 nsCOMPtr profD = mProfD;
5904 nsCOMPtr profileLock = mProfileLock;
5905 rv = HandleDetectedDowngrade(profD, nativeApp, profileSvc, profileLock,
5906 compatResult.lastVersion,
5907 compatResult.isDifferentInstall);
5908 if (rv == NS_ERROR_LAUNCHED_CHILD_PROCESS || rv == NS_ERROR_ABORT) {
5909 *aExitFlag = true;
5910 return 0;
5911 }
5912 }
5913#endif
5914
5915 rv = mDirProvider.SetProfile(mProfD, mProfLD);
5916 NS_ENSURE_SUCCESS(rv, 1)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 5916); return 1; } } while (false)
;
5917
5918 //////////////////////// NOW WE HAVE A PROFILE ////////////////////////
5919
5920 mozilla::Telemetry::SetProfileDir(mProfD);
5921
5922 if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER(1 << 3)) {
5923 MakeOrSetMinidumpPath(mProfD);
5924 }
5925
5926 CrashReporter::SetProfileDirectory(mProfD);
5927
5928#ifdef MOZ_ASAN_REPORTER
5929 // In ASan reporter builds, we need to set ASan's log_path as early as
5930 // possible, so it dumps its errors into files there instead of using
5931 // the default stderr location. Since this is crucial for ASan reporter
5932 // to work at all (and we don't want people to use a non-functional
5933 // ASan reporter build), all failures while setting log_path are fatal.
5934 setASanReporterPath(mProfD);
5935
5936 // Export to env for child processes
5937 SaveFileToEnv("ASAN_REPORTER_PATH", mProfD);
5938#endif
5939
5940 bool lastStartupWasCrash = CheckLastStartupWasCrash();
5941
5942 CrashReporter::RecordAnnotationBool(
5943 CrashReporter::Annotation::LastStartupWasCrash, lastStartupWasCrash);
5944
5945 if (CheckArg("purgecaches") || PR_GetEnv("MOZ_PURGE_CACHES") ||
5946 lastStartupWasCrash || gSafeMode) {
5947 cachesOK = false;
5948 }
5949
5950 CrashReporter::RecordAnnotationBool(
5951 CrashReporter::Annotation::StartupCacheValid,
5952 cachesOK && compatResult.isCompatible);
5953
5954#ifdef XP_MACOSX
5955 static bool status = nsCocoaFeatures::ProcessIsRosettaTranslated();
5956 CrashReporter::RecordAnnotationBool(CrashReporter::Annotation::RosettaStatus,
5957 status);
5958 mozilla::glean::widget::rosetta_status.Set(status);
5959#endif
5960
5961 // Every time a profile is loaded by a build with a different version,
5962 // it updates the compatibility.ini file saying what version last wrote
5963 // the fastload caches. On subsequent launches if the version matches,
5964 // there is no need for re-registration. If the user loads the same
5965 // profile in different builds the component registry must be
5966 // re-generated to prevent mysterious component loading failures.
5967 //
5968 bool startupCacheValid = true;
5969
5970 if (!cachesOK || !compatResult.isCompatible) {
5971 QuotaManager::InvalidateQuotaCache(
5972 QuotaManager::CacheInvalidationLevel::Soft);
5973
5974 startupCacheValid = RemoveComponentRegistries(mProfD, mProfLD, false);
5975
5976 // Rewrite compatibility.ini to match the current build. The next run
5977 // should attempt to invalidate the caches if either this run is safe mode
5978 // or the attempt to invalidate the caches this time failed.
5979 WriteVersion(mProfD, version, osABI, mDirProvider.GetGREDir(),
5980 mAppData->directory, gSafeMode || !startupCacheValid);
5981 }
5982
5983 if (!startupCacheValid) StartupCache::IgnoreDiskCache();
5984
5985 if (flagFile) {
5986 flagFile->Remove(true);
5987 }
5988
5989 // Flush any pending page load events.
5990 mozilla::glean_pings::Pageload.Submit("startup"_ns);
5991
5992 if (!isBackgroundTaskMode) {
5993#ifdef USE_GLX_TEST1
5994 GfxInfo::FireGLXTestProcess();
5995#endif
5996#ifdef MOZ_WAYLAND1
5997 // Make sure we have wayland connection for main thread.
5998 // It's used as template to create display connections
5999 // for different threads.
6000 if (IsWaylandEnabled()) {
6001 (void)WaylandDisplayGet();
6002 }
6003#endif
6004#ifdef MOZ_WIDGET_GTK1
6005 nsAppShell::InstallTermSignalHandler();
6006#endif
6007 }
6008
6009 return 0;
6010}
6011
6012#if defined(MOZ_SANDBOX1)
6013void AddSandboxAnnotations() MOZ_CAN_RUN_SCRIPT_BOUNDARY {
6014 CrashReporter::RecordAnnotationU32(
6015 CrashReporter::Annotation::ContentSandboxLevel,
6016 GetEffectiveContentSandboxLevel());
6017 CrashReporter::RecordAnnotationU32(CrashReporter::Annotation::GpuSandboxLevel,
6018 GetEffectiveGpuSandboxLevel());
6019
6020 // Include whether or not this instance is capable of content sandboxing
6021 bool sSandboxCapable = false;
6022
6023# if defined(XP_WIN)
6024 // All supported Windows versions support some level of content sandboxing
6025 sSandboxCapable = true;
6026# elif defined(XP_MACOSX)
6027 // All supported OS X versions are capable
6028 sSandboxCapable = true;
6029# elif defined(XP_LINUX1)
6030 sSandboxCapable = SandboxInfo::Get().CanSandboxContent();
6031# elif defined(__OpenBSD__)
6032 sSandboxCapable = true;
6033 StartOpenBSDSandbox(GeckoProcessType_Default);
6034# endif
6035
6036 CrashReporter::RecordAnnotationBool(
6037 CrashReporter::Annotation::ContentSandboxCapable, sSandboxCapable);
6038}
6039#endif /* MOZ_SANDBOX */
6040
6041/*
6042 * XRE_mainRun - Command line startup, profile migration, and
6043 * the calling of appStartup->Run().
6044 */
6045nsresult XREMain::XRE_mainRun() {
6046 nsresult rv = NS_OK;
6047 NS_ASSERTION(mScopedXPCOM, "Scoped xpcom not initialized.")do { if (!(mScopedXPCOM)) { NS_DebugBreak(NS_DEBUG_ASSERTION,
"Scoped xpcom not initialized.", "mScopedXPCOM", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6047); MOZ_PretendNoReturn(); } } while (0)
;
6048
6049#if defined(XP_WIN)
6050 RefPtr<mozilla::DllServices> dllServices(mozilla::DllServices::Get());
6051 dllServices->StartUntrustedModulesProcessor(false);
6052 auto dllServicesDisable =
6053 MakeScopeExit([&dllServices]() { dllServices->DisableFull(); });
6054
6055 mozilla::mscom::InitProfilerMarkers();
6056#endif // defined(XP_WIN)
6057
6058 // We need the appStartup pointer to span multiple scopes, so we declare
6059 // it here.
6060 nsCOMPtr<nsIAppStartup> appStartup;
6061 // Ditto with the command line.
6062 nsCOMPtr<nsICommandLineRunner> cmdLine;
6063
6064 {
6065#ifdef XP_MACOSX
6066 // In this scope, create an autorelease pool that will leave scope with
6067 // it just before entering our event loop.
6068 mozilla::MacAutoreleasePool pool;
6069#endif
6070
6071 rv = mScopedXPCOM->SetWindowCreator(mNativeApp);
6072 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6072); return
NS_ERROR_FAILURE; } } while (false)
;
6073
6074 // Record platform annotations which need XPCOM initialized.
6075 CrashReporter::RecordXPCOMPlatformAnnotations();
6076
6077 // tell the crash reporter to also send the release channel
6078 nsCOMPtr<nsIPrefService> prefs =
6079 do_GetService("@mozilla.org/preferences-service;1", &rv);
6080 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6081 nsCOMPtr<nsIPrefBranch> defaultPrefBranch;
6082 rv = prefs->GetDefaultBranch(nullptr, getter_AddRefs(defaultPrefBranch));
6083
6084 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6085 nsAutoCString sval;
6086 rv = defaultPrefBranch->GetCharPref("app.update.channel", sval);
6087 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6088 CrashReporter::RecordAnnotationNSCString(
6089 CrashReporter::Annotation::ReleaseChannel, sval);
6090 }
6091 }
6092 }
6093 // Needs to be set after xpcom initialization.
6094 bool includeContextHeap = Preferences::GetBool(
6095 "toolkit.crashreporter.include_context_heap", false);
6096 CrashReporter::SetIncludeContextHeap(includeContextHeap);
6097
6098#if defined(XP_LINUX1) && !defined(ANDROID)
6099 PR_CreateThread(PR_USER_THREAD, AnnotateLSBRelease, nullptr,
6100 PR_PRIORITY_LOW, PR_GLOBAL_THREAD, PR_UNJOINABLE_THREAD, 0);
6101#endif
6102
6103 if (mStartOffline) {
6104 nsCOMPtr<nsIIOService> io(
6105 do_GetService("@mozilla.org/network/io-service;1"));
6106 NS_ENSURE_TRUE(io, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(io)), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "io" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6106); return NS_ERROR_FAILURE; } } while (false)
;
6107 io->SetManageOfflineStatus(false);
6108 io->SetOffline(true);
6109 }
6110
6111 if (!mOriginToForceQUIC.IsEmpty()) {
6112 PR_SetEnv(ToNewCString("MOZ_FORCE_QUIC_ON="_ns + mOriginToForceQUIC));
6113 }
6114
6115#ifdef XP_WIN
6116 mozilla::DllPrefetchExperimentRegistryInfo prefetchRegInfo;
6117 mozilla::AlteredDllPrefetchMode dllPrefetchMode =
6118 prefetchRegInfo.GetAlteredDllPrefetchMode();
6119
6120 if (!PR_GetEnv("XRE_NO_DLL_READAHEAD") &&
6121 dllPrefetchMode != mozilla::AlteredDllPrefetchMode::NoPrefetch) {
6122 nsCOMPtr<nsIFile> greDir = mDirProvider.GetGREDir();
6123 nsAutoString path;
6124 rv = greDir->GetPath(path);
6125 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6126 // We use the presence of a path argument inside the thread to determine
6127 // which list of Dlls to use. The old list does not need access to the
6128 // GRE dir, so the path argument is voided.
6129 if (dllPrefetchMode !=
6130 mozilla::AlteredDllPrefetchMode::OptimizedPrefetch) {
6131 path.SetIsVoid(true);
6132 }
6133
6134 NS_DispatchBackgroundTask(
6135 NS_NewRunnableFunction("ReadAheadDlls", [path = std::move(path)] {
6136 ReadAheadDlls(path.IsVoid() ? nullptr : path.get());
6137 }));
6138 }
6139 }
6140#endif
6141
6142 if (gDoMigration) {
6143 nsCOMPtr<nsIFile> file;
6144 mDirProvider.GetAppDir()->Clone(getter_AddRefs(file));
6145 file->AppendNative("override.ini"_ns);
6146 nsINIParsernsINIParser_internal parser;
6147 nsresult rv = parser.Init(file);
6148 // if override.ini doesn't exist, also check for distribution.ini
6149 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6150 bool persistent;
6151 mDirProvider.GetFile(XRE_APP_DISTRIBUTION_DIR"XREAppDist", &persistent,
6152 getter_AddRefs(file));
6153 file->AppendNative("distribution.ini"_ns);
6154 rv = parser.Init(file);
6155 }
6156 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6157 nsAutoCString buf;
6158 rv = parser.GetString("XRE", "EnableProfileMigrator", buf);
6159 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
6160 if (buf[0] == '0' || buf[0] == 'f' || buf[0] == 'F') {
6161 gDoMigration = false;
6162 }
6163 }
6164 }
6165 }
6166
6167 // We'd like to initialize the JSContext *after* reading the user prefs.
6168 // Unfortunately that's not possible if we have to do profile migration
6169 // because that requires us to execute JS before reading user prefs.
6170 // Restarting the browser after profile migration would fix this. See
6171 // bug 1592523.
6172 bool initializedJSContext = false;
6173
6174 {
6175 // Profile Migration
6176 if (mAppData->flags & NS_XRE_ENABLE_PROFILE_MIGRATOR(1 << 1) && gDoMigration) {
6177 gDoMigration = false;
6178
6179 xpc::InitializeJSContext();
6180 initializedJSContext = true;
6181
6182 nsCOMPtr<nsIProfileMigrator> pm(
6183 do_CreateInstance(NS_PROFILEMIGRATOR_CONTRACTID"@mozilla.org/toolkit/profile-migrator;1"));
6184 if (pm) {
6185 nsAutoCString aKey;
6186 nsAutoCString aProfilePath;
6187 if (gDoProfileReset) {
6188 // Automatically migrate from the current application if we just
6189 // reset the profile.
6190 nsCOMPtr<nsIFile> rootDir = gResetOldProfile->GetRootDir();
6191 nsAutoString path;
6192 rootDir->GetPath(path);
6193 CopyUTF16toUTF8(path, aProfilePath);
6194
6195 nsCString storeID;
6196 gResetOldProfile->GetStoreID(storeID);
6197 if (!storeID.IsVoid()) {
6198 aKey = "firefox-selectable-profile";
6199 // In the case that Firefox is launched with --reset-profile,
6200 // the storeID and path env variables won't be set, so we set
6201 // them here if we are in a profile with a storeID.
6202 nsAutoCString envStoreID("SELECTABLE_PROFILE_RESET_STORE_ID=");
6203 envStoreID.Append(storeID);
6204 SaveToEnv(envStoreID.get());
6205
6206 nsAutoCString envProfilePath("SELECTABLE_PROFILE_RESET_PATH=");
6207 envProfilePath.Append(aProfilePath);
6208 SaveToEnv(envProfilePath.get());
6209 } else {
6210 aKey = MOZ_APP_NAME"firefox";
6211 }
6212 }
6213#ifdef XP_MACOSX
6214 // Necessary for migration wizard to be accessible.
6215 InitializeMacApp();
6216#endif
6217 pm->Migrate(&mDirProvider, aKey, aProfilePath);
6218 }
6219 }
6220
6221 if (gDoProfileReset) {
6222 if (!initializedJSContext) {
6223 xpc::InitializeJSContext();
6224 initializedJSContext = true;
6225 }
6226
6227 const RefPtr<nsToolkitProfileService> profileSvc = mProfileSvc;
6228 const nsCOMPtr<nsIToolkitProfile> oldProfile = gResetOldProfile;
6229 nsresult backupCreated = ProfileResetCleanup(profileSvc, oldProfile);
6230 if (NS_FAILED(backupCreated)((bool)(__builtin_expect(!!(NS_FAILED_impl(backupCreated)), 0
)))
) {
6231 NS_WARNING("Could not cleanup the profile that was reset")NS_DebugBreak(NS_DEBUG_WARNING, "Could not cleanup the profile that was reset"
, nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
6231)
;
6232 }
6233 }
6234 }
6235
6236 // Initialize user preferences before notifying startup observers so they're
6237 // ready in time for early consumers, such as the component loader.
6238 mDirProvider.InitializeUserPrefs();
6239
6240 // Now that preferences are loaded the profile service may be able to
6241 // determine the correct startup profile.
6242 mProfileSvc->UpdateCurrentProfile();
6243
6244 // Now that all (user) prefs have been loaded we can initialize the main
6245 // thread's JSContext.
6246 if (!initializedJSContext) {
6247 xpc::InitializeJSContext();
6248 }
6249
6250 // Finally, now that JS has been initialized, we can finish pref loading.
6251 // This needs to happen after JS and XPConnect initialization because
6252 // AutoConfig files require JS execution. Note that this means AutoConfig
6253 // files can't override JS engine start-up prefs.
6254 mDirProvider.FinishInitializingUserPrefs();
6255
6256 // Now that the profiler, directory services, and prefs have been
6257 // initialized we can find the download directory, where the profiler can
6258 // write profiles when user stops the profiler using POSIX signal handling.
6259 //
6260 // It's possible to start and stop the profiler by sending POSIX signals to
6261 // the profiler binary when Firefox is frozen. At the time when stop signal
6262 // is handled, Firefox stops the profiler and dumps the profile to disk. But
6263 // getting the download directory is not really possible at that time
6264 // because main thread will be unresponsive. That's why we are getting this
6265 // information right now.
6266 profiler_lookup_async_signal_dump_directory();
6267
6268 // Do a canary load of a JS based module here. This will help us detect
6269 // missing resources during startup and make us react appropriate, that
6270 // is inform the user before exiting with a crash.
6271 {
6272 mozilla::dom::AutoJSAPI jsapi;
6273 MOZ_ALWAYS_TRUE(jsapi.Init(xpc::PrivilegedJunkScope()))do { if ((__builtin_expect(!!(jsapi.Init(xpc::PrivilegedJunkScope
())), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "jsapi.Init(xpc::PrivilegedJunkScope())", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6273); AnnotateMozCrashReason("MOZ_CRASH(" "jsapi.Init(xpc::PrivilegedJunkScope())"
")"); do { MOZ_CrashSequence(__null, 6273); __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
6274 JS::Rooted<JSObject*> mod(jsapi.cx());
6275 // AppConstants.sys.mjs is small, widely used and most likely will
6276 // never go away.
6277 rv = mozJSModuleLoader::Get()->ImportESModule(
6278 jsapi.cx(), "resource://gre/modules/AppConstants.sys.mjs"_ns, &mod);
6279 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6280 return NS_ERROR_OMNIJAR_OR_DIR_MISSING;
6281 }
6282 }
6283
6284#if defined(MOZ_SANDBOX1) && defined(XP_WIN)
6285 // Now that we have preferences and the directory provider, we can
6286 // finish initializing SandboxBroker. This must happen before the GFX
6287 // platform is initialized (which will launch the GPU process), which
6288 // occurs when the "app-startup" category is started up below
6289 //
6290 // After this completes, we are ready to launch sandboxed processes
6291 mozilla::SandboxBroker::GeckoDependentInitialize();
6292#endif
6293
6294 nsCOMPtr<nsIFile> workingDir;
6295 rv = NS_GetSpecialDirectory(NS_OS_CURRENT_WORKING_DIR"CurWorkD",
6296 getter_AddRefs(workingDir));
6297 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6298 // No working dir? This can happen if it gets deleted before we start.
6299 workingDir = nullptr;
6300 }
6301
6302 cmdLine = new nsCommandLine();
6303
6304 rv = cmdLine->Init(gArgc, gArgv, workingDir,
6305 nsICommandLine::STATE_INITIAL_LAUNCH);
6306 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6306); return
NS_ERROR_FAILURE; } } while (false)
;
6307
6308 // "app-startup" is the name of both the category and the event
6309 NS_CreateServicesFromCategory("app-startup", cmdLine, "app-startup",
6310 nullptr);
6311
6312 appStartup = components::AppStartup::Service();
6313 NS_ENSURE_TRUE(appStartup, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(appStartup)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "appStartup" ") failed",
nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6313
); return NS_ERROR_FAILURE; } } while (false)
;
6314
6315 mDirProvider.DoStartup();
6316
6317#ifdef XP_WIN
6318 // It needs to be called on the main thread because it has to use
6319 // nsObserverService.
6320 EnsureWin32kInitialized();
6321#endif
6322
6323 // As FilePreferences need the profile directory, we must initialize right
6324 // here.
6325 mozilla::FilePreferences::InitDirectoriesAllowlist();
6326 mozilla::FilePreferences::InitPrefs();
6327
6328 nsCString userAgentLocale;
6329 LocaleService::GetInstance()->GetAppLocaleAsBCP47(userAgentLocale);
6330 CrashReporter::RecordAnnotationNSCString(
6331 CrashReporter::Annotation::useragent_locale, userAgentLocale);
6332
6333 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
6334 /* Special-case services that need early access to the command
6335 line. */
6336 nsCOMPtr<nsIObserverService> obsService =
6337 mozilla::services::GetObserverService();
6338 if (obsService) {
6339 obsService->NotifyObservers(cmdLine, "command-line-startup", nullptr);
6340 }
6341 }
6342
6343#ifdef XP_WIN
6344 // Hack to sync up the various environment storages. XUL_APP_FILE is special
6345 // in that it comes from a different CRT (firefox.exe's static-linked copy).
6346 // Ugly details in http://bugzil.la/1175039#c27
6347 char appFile[MAX_PATH];
6348 if (GetEnvironmentVariableA("XUL_APP_FILE", appFile, sizeof(appFile))) {
6349 SmprintfPointer saved = mozilla::Smprintf("XUL_APP_FILE=%s", appFile);
6350 // We intentionally leak the string here since it is required by
6351 // PR_SetEnv.
6352 PR_SetEnv(saved.release());
6353 }
6354#endif
6355
6356 mozilla::AppShutdown::SaveEnvVarsForPotentialRestart();
6357
6358 // clear out any environment variables which may have been set
6359 // during the relaunch process now that we know we won't be relaunching.
6360 SaveToEnv("XRE_PROFILE_PATH=");
6361 SaveToEnv("XRE_PROFILE_LOCAL_PATH=");
6362 SaveToEnv("XRE_START_OFFLINE=");
6363 SaveToEnv("XUL_APP_FILE=");
6364 SaveToEnv("XRE_BINARY_PATH=");
6365 SaveToEnv("XRE_RESTARTED_BY_PROFILE_MANAGER=");
6366
6367 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
6368#ifdef XP_MACOSX
6369 bool isBackgroundTaskMode = false;
6370# ifdef MOZ_BACKGROUNDTASKS1
6371 isBackgroundTaskMode = BackgroundTasks::IsBackgroundTaskMode();
6372# endif
6373 if (!isBackgroundTaskMode) {
6374 rv = appStartup->CreateHiddenWindow();
6375 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6375); return
NS_ERROR_FAILURE; } } while (false)
;
6376 }
6377#endif
6378
6379#ifdef XP_WIN
6380 Preferences::RegisterCallbackAndCall(
6381 RegisterApplicationRestartChanged,
6382 PREF_WIN_REGISTER_APPLICATION_RESTART);
6383 SetupAlteredPrefetchPref();
6384# if defined(MOZ_LAUNCHER_PROCESS)
6385 SetupLauncherProcessPref();
6386# endif // defined(MOZ_LAUNCHER_PROCESS)
6387# if defined(MOZ_DEFAULT_BROWSER_AGENT)
6388# if defined(MOZ_BACKGROUNDTASKS1)
6389 // The backgroundtask profile is not a browsing profile, let alone the new
6390 // default profile, so don't mirror its properties into the registry.
6391 if (!BackgroundTasks::IsBackgroundTaskMode())
6392# endif // defined(MOZ_BACKGROUNDTASKS)
6393 {
6394 SetupSkeletonUIPrefs();
6395 Preferences::RegisterCallbackAndCall(
6396 &OnDefaultAgentTelemetryPrefChanged,
6397 kPrefHealthReportUploadEnabled);
6398 Preferences::RegisterCallbackAndCall(
6399 &OnDefaultAgentTelemetryPrefChanged, kPrefDefaultAgentEnabled);
6400
6401 Preferences::RegisterCallbackAndCall(
6402 &OnDefaultAgentRemoteSettingsPrefChanged,
6403 kPrefServicesSettingsServer);
6404
6405 Preferences::RegisterCallbackAndCall(
6406 &OnSetDefaultBrowserUserChoicePrefChanged,
6407 kPrefSetDefaultBrowserUserChoicePref);
6408
6409 SetDefaultAgentLastRunTime();
6410 }
6411# endif // defined(MOZ_DEFAULT_BROWSER_AGENT)
6412#endif
6413
6414#if defined(MOZ_WIDGET_GTK1)
6415 // Clear the environment variables so they won't be inherited by child
6416 // processes and confuse things.
6417 for (const auto& name : kStartupTokenNames) {
6418 g_unsetenv(name.get());
6419 }
6420 nsAppShell::InitSessionRestore();
6421#endif
6422
6423#ifdef XP_MACOSX
6424 InitializeMacApp();
6425
6426 // we re-initialize the command-line service and do appleevents munging
6427 // after we are sure that we're not restarting
6428 cmdLine = new nsCommandLine();
6429
6430 char** tempArgv = static_cast<char**>(malloc(gArgc * sizeof(char*)));
6431 for (int i = 0; i < gArgc; i++) {
6432 tempArgv[i] = strdup(gArgv[i]);
6433 }
6434 CommandLineServiceMac::SetupMacCommandLine(gArgc, tempArgv, false);
6435 rv = cmdLine->Init(gArgc, tempArgv, workingDir,
6436 nsICommandLine::STATE_INITIAL_LAUNCH);
6437 free(tempArgv);
6438 NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "NS_ERROR_FAILURE", static_cast
<uint32_t>(__rv), name ? " (" : "", name ? name : "", name
? ")" : ""); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6438); return
NS_ERROR_FAILURE; } } while (false)
;
6439
6440# if defined(MOZILLA_OFFICIAL) || defined(DMG_INSTALL_HELPER_DEBUG)
6441 // Check if we're running from a DMG or an app translocated location and
6442 // allow the user to install to the Applications directory.
6443 if (MacRunFromDmgUtils::MaybeInstallAndRelaunch()) {
6444 appStartup->Quit(nsIAppStartup::eForceQuit, 0);
6445 }
6446# endif
6447#endif
6448
6449#if defined(XP_MACOSX)
6450 RegisterASWebAuthSessionObservers();
6451#endif
6452
6453 nsCOMPtr<nsIObserverService> obsService =
6454 mozilla::services::GetObserverService();
6455 if (obsService)
6456 obsService->NotifyObservers(nullptr, "final-ui-startup", nullptr);
6457
6458 (void)appStartup->DoneStartingUp();
6459
6460 CrashReporter::RecordAnnotationBool(
6461 CrashReporter::Annotation::StartupCrash, false);
6462
6463 AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed);
6464 }
6465
6466 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
6467 rv = cmdLine->Run();
6468 NS_ENSURE_SUCCESS_LOG(rv, NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(((bool)(__builtin_expect(!!(!
NS_FAILED_impl(rv)), 1))))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "NS_SUCCEEDED(rv)" ") failed", nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6468); gLogConsoleErrors = true; return NS_ERROR_FAILURE; }
} while (0)
;
6469 }
6470
6471 if (!AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
6472#if defined(MOZ_HAS_REMOTE1)
6473 // if we have X remote support, start listening for requests on the
6474 // proxy window.
6475 if (gRemoteService) {
6476 gRemoteService->StartupServer();
6477 gStartupLock = nullptr;
6478 }
6479#endif
6480
6481 mNativeApp->Enable();
6482 }
6483
6484 // Send Telemetry about Gecko version and buildid
6485 mozilla::glean::gecko::version.Set(nsDependentCString(gAppData->version));
6486 mozilla::glean::gecko::build_id.Set(nsDependentCString(gAppData->buildID));
6487
6488#if defined(MOZ_SANDBOX1) && defined(XP_LINUX1)
6489 // If we're on Linux, we now have information about the OS capabilities
6490 // available to us.
6491 SandboxInfo sandboxInfo = SandboxInfo::Get();
6492 // If we need telemetry probes for sandboxInfo bits, they can go here.
6493
6494 CrashReporter::RecordAnnotationU32(
6495 CrashReporter::Annotation::ContentSandboxCapabilities,
6496 sandboxInfo.AsInteger());
6497#endif /* MOZ_SANDBOX && XP_LINUX */
6498
6499#if defined(XP_WIN)
6500 LauncherResult<bool> isAdminWithoutUac = IsAdminWithoutUac();
6501 if (isAdminWithoutUac.isOk()) {
6502 glean::os_environment::is_admin_without_uac.Set(
6503 isAdminWithoutUac.unwrap());
6504 }
6505#endif /* XP_WIN */
6506
6507#if defined(MOZ_SANDBOX1)
6508 AddSandboxAnnotations();
6509#endif /* MOZ_SANDBOX */
6510
6511 mProfileSvc->CompleteStartup();
6512 }
6513
6514#ifdef MOZ_BACKGROUNDTASKS1
6515 if (BackgroundTasks::IsBackgroundTaskMode()) {
6516 // In background task mode, we don't fire various delayed initialization
6517 // notifications, which in the regular browser is how startup crash tracking
6518 // is marked as finished. Here, getting this far means we don't have a
6519 // startup crash.
6520 rv = appStartup->TrackStartupCrashEnd();
6521 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6521); return rv; } } while (false)
;
6522
6523 // We never open a window, but don't want to exit immediately.
6524 rv = appStartup->EnterLastWindowClosingSurvivalArea();
6525 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6525); return rv; } } while (false)
;
6526
6527 // Avoid some small differences in initialization order across platforms.
6528 nsCOMPtr<nsIPowerManagerService> powerManagerService =
6529 do_GetService(POWERMANAGERSERVICE_CONTRACTID"@mozilla.org/power/powermanagerservice;1");
6530 nsCOMPtr<nsIStringBundleService> stringBundleService =
6531 do_GetService(NS_STRINGBUNDLE_CONTRACTID"@mozilla.org/intl/stringbundle;1");
6532
6533 rv = BackgroundTasks::RunBackgroundTask(cmdLine);
6534 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6534); return rv; } } while (false)
;
6535 }
6536#endif
6537
6538 // We're entering the main run loop now, so we don't need to keep holding onto
6539 // the `nsICommandLineRunner` anymore.
6540 cmdLine = nullptr;
6541
6542#ifdef ACCESSIBILITY1
6543 // If accessibility.force_disabled is force enabled, start accessibility
6544 // now rather than waiting for something to request it. This is the one
6545 // place we can do this reliably on every platform.
6546 a11y::MaybeStartForceEnabled();
6547#endif
6548
6549 {
6550 rv = appStartup->Run();
6551 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6552 NS_ERROR("failed to run appstartup")do { NS_DebugBreak(NS_DEBUG_ASSERTION, "failed to run appstartup"
, "Error", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp",
6552); MOZ_PretendNoReturn(); } while (0)
;
6553 gLogConsoleErrors = true;
6554 }
6555 }
6556
6557 return rv;
6558}
6559
6560#if defined(MOZ_WIDGET_ANDROID)
6561static already_AddRefed<nsIFile> GreOmniPath(int argc, char** argv) {
6562 nsresult rv;
6563
6564 const char* path = nullptr;
6565 ArgResult ar = CheckArg(argc, argv, "greomni", &path, CheckArgFlag::None);
6566 if (ar == ARG_BAD) {
6567 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError),
6568 "Error: argument --greomni requires a path argument\n");
6569 return nullptr;
6570 }
6571
6572 if (!path) return nullptr;
6573
6574 nsCOMPtr<nsIFile> greOmni;
6575 rv = XRE_GetFileFromPath(path, getter_AddRefs(greOmni));
6576 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6577 PR_fprintf(PR_STDERRPR_GetSpecialFD(PR_StandardError), "Error: argument --greomni requires a valid path\n");
6578 return nullptr;
6579 }
6580
6581 return greOmni.forget();
6582}
6583#endif
6584
6585/*
6586 * XRE_main - A class based main entry point used by most platforms.
6587 * Note that on OSX, aAppData->xreDirectory will point to
6588 * .app/Contents/Resources.
6589 */
6590int XREMain::XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) {
6591 gArgc = argc;
6592 gArgv = argv;
6593 ScopedLogging log;
6594
6595 mozilla::LogModule::Init(gArgc, gArgv);
6596
6597#ifndef XP_LINUX1
6598 NS_SetCurrentThreadName("MainThread");
6599#endif
6600
6601 AUTO_BASE_PROFILER_LABEL("XREMain::XRE_main (around Gecko Profiler)", OTHER)::mozilla::baseprofiler::AutoProfilerLabel raiiObject6601( "XREMain::XRE_main (around Gecko Profiler)"
, nullptr, ::mozilla::baseprofiler::ProfilingCategoryPair::OTHER
)
;
6602 AUTO_PROFILER_INITmozilla::AutoProfilerInit raiiObject6602;
6603 AUTO_PROFILER_LABEL("XREMain::XRE_main", OTHER)mozilla::AutoProfilerLabel raiiObject6603( "XREMain::XRE_main"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
6604
6605#ifdef XP_MACOSX
6606 // We call this early because it will kick off a background-thread task
6607 // to register the fonts, and we'd like it to have a chance to complete
6608 // before gfxPlatform initialization actually requires it.
6609 auto _supplementalFontThread = gfxPlatformMac::RegisterSupplementalFonts();
6610#endif
6611
6612#ifdef MOZ_WIDGET_ANDROID
6613 // We call the early because we run system font API on a background-thread
6614 // to initialize internal font API data in Android. (Bug 1895926)
6615 gfxAndroidPlatform::InitializeFontAPI();
6616#endif
6617
6618#ifdef MOZ_CODE_COVERAGE
6619 CodeCoverageHandler::Init();
6620#endif
6621
6622 nsresult rv = NS_OK;
6623
6624 if (aConfig.appData) {
6625 mAppData = MakeUnique<XREAppData>(*aConfig.appData);
6626 } else {
6627 MOZ_RELEASE_ASSERT(aConfig.appDataPath)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aConfig.appDataPath)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aConfig.appDataPath))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("aConfig.appDataPath"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6627); AnnotateMozCrashReason
("MOZ_RELEASE_ASSERT" "(" "aConfig.appDataPath" ")"); do { MOZ_CrashSequence
(__null, 6627); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6628 nsCOMPtr<nsIFile> appini;
6629 rv = XRE_GetFileFromPath(aConfig.appDataPath, getter_AddRefs(appini));
6630 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6631 Output(true, "Error: unrecognized path: %s\n", aConfig.appDataPath);
6632 return 1;
6633 }
6634
6635 mAppData = MakeUnique<XREAppData>();
6636 rv = XRE_ParseAppData(appini, *mAppData);
6637 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6638 Output(true, "Couldn't read application.ini");
6639 return 1;
6640 }
6641
6642 appini->GetParent(getter_AddRefs(mAppData->directory));
6643 }
6644
6645 const char* appRemotingName = getenv("MOZ_APP_REMOTINGNAME");
6646 if (appRemotingName) {
6647 mAppData->remotingName = appRemotingName;
6648 } else if (!mAppData->remotingName) {
6649 mAppData->remotingName = mAppData->name;
6650 }
6651 // used throughout this file
6652 gAppData = mAppData.get();
6653
6654 nsCOMPtr<nsIFile> binFile;
6655 rv = XRE_GetBinaryPath(getter_AddRefs(binFile));
6656 NS_ENSURE_SUCCESS(rv, 1)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6656); return 1; } } while (false)
;
6657
6658 rv = binFile->GetPath(gAbsoluteArgv0Path);
6659 NS_ENSURE_SUCCESS(rv, 1)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6659); return 1; } } while (false)
;
6660
6661 if (!mAppData->xreDirectory) {
6662 nsCOMPtr<nsIFile> greDir;
6663
6664#if defined(MOZ_WIDGET_ANDROID)
6665 greDir = GreOmniPath(argc, argv);
6666 if (!greDir) {
6667 return 2;
6668 }
6669#else
6670 rv = binFile->GetParent(getter_AddRefs(greDir));
6671 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return 2;
6672#endif
6673
6674#ifdef XP_MACOSX
6675 nsCOMPtr<nsIFile> parent;
6676 greDir->GetParent(getter_AddRefs(parent));
6677 greDir = parent.forget();
6678 greDir->AppendNative("Resources"_ns);
6679#elif defined(XP_IOS)
6680 // FIXME: Consider looking up the GeckoView.framework bundle directly,
6681 // rather than deriving it from XRE_GetBinaryPath on iOS. This may be more
6682 // resilient especially once we properly bundle XUL into a separate
6683 // framework or support multiple embedders.
6684 rv = greDir->AppendNative("Frameworks"_ns);
6685 NS_ENSURE_SUCCESS(rv, 2)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "2", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6685); return 2; } } while (false)
;
6686 rv = greDir->AppendNative("GeckoView.framework"_ns);
6687 NS_ENSURE_SUCCESS(rv, 2)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "2", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6687); return 2; } } while (false)
;
6688 rv = greDir->AppendNative("Frameworks"_ns);
6689 NS_ENSURE_SUCCESS(rv, 2)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "2", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6689); return 2; } } while (false)
;
6690#endif
6691
6692 mAppData->xreDirectory = greDir;
6693 }
6694
6695#if defined(MOZ_WIDGET_ANDROID)
6696 nsCOMPtr<nsIFile> dataDir;
6697 rv = binFile->GetParent(getter_AddRefs(dataDir));
6698 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return 2;
6699
6700 mAppData->directory = dataDir;
6701#else
6702 if (aConfig.appData && aConfig.appDataPath) {
6703 mAppData->xreDirectory->Clone(getter_AddRefs(mAppData->directory));
6704 mAppData->directory->AppendNative(nsDependentCString(aConfig.appDataPath));
6705 }
6706#endif
6707
6708 if (!mAppData->directory) {
6709 mAppData->directory = mAppData->xreDirectory;
6710 }
6711
6712#if defined(XP_WIN)
6713# if defined(MOZ_SANDBOX1)
6714 mAppData->sandboxBrokerServices = aConfig.sandboxBrokerServices;
6715# endif // defined(MOZ_SANDBOX)
6716
6717# if defined(_M_IX86) || defined(_M_X64)
6718 {
6719 DebugOnly<bool> result = WindowsMsctfInitialization();
6720 MOZ_ASSERT(result)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(result)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(result))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("result", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6720); AnnotateMozCrashReason("MOZ_ASSERT" "(" "result" ")"
); do { MOZ_CrashSequence(__null, 6720); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6721 }
6722# endif // _M_IX86 || _M_X64
6723
6724 // Bug 1924623: Detouring VariantClear resulted in a huge crash spike for
6725 // Thunderbird, so let's only do that for Firefox.
6726# ifdef MOZ_BUILD_APP_IS_BROWSER1
6727 {
6728 DebugOnly<bool> result = WindowsOleAut32Initialization();
6729 MOZ_ASSERT(result)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(result)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(result))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("result", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "result" ")"
); do { MOZ_CrashSequence(__null, 6729); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6730 }
6731# endif // MOZ_BUILD_APP_IS_BROWSER
6732
6733#endif // defined(XP_WIN)
6734
6735 // Once we unset the exception handler, we lose the ability to properly
6736 // detect hangs -- they show up as crashes. We do this as late as possible.
6737 // In particular, after ProcessRuntime is destroyed on Windows.
6738 auto unsetExceptionHandler = MakeScopeExit([&] {
6739 if (mAppData->flags & NS_XRE_ENABLE_CRASH_REPORTER(1 << 3)) {
6740 nsresult rv = CrashReporter::UnsetExceptionHandler();
6741 CrashReporter::OOPDeinit();
6742 return rv;
6743 }
6744 return NS_OK;
6745 });
6746
6747#if defined(MOZ_WIDGET_ANDROID)
6748 CrashReporter::SetCrashHelperPipes(aConfig.crashChildNotificationSocket,
6749 aConfig.crashHelperSocket);
6750#endif // defined(MOZ_WIDGET_ANDROID)
6751
6752 mozilla::AutoIOInterposer ioInterposerGuard;
6753 ioInterposerGuard.Init();
6754
6755#if defined(XP_WIN)
6756 // We should have already done this when we created the skeleton UI. However,
6757 // there is code in here which needs xul in order to work, like EnsureMTA. It
6758 // should be setup that running it again is safe.
6759 mozilla::mscom::ProcessRuntime msCOMRuntime;
6760#endif
6761
6762 // init
6763 bool exit = false;
6764 int result = XRE_mainInit(&exit);
6765 if (result != 0 || exit) return result;
6766
6767 // If we exit gracefully, remove the startup crash canary file.
6768 auto cleanup = MakeScopeExit([&]() -> nsresult {
6769 if (mProfLD) {
6770 nsCOMPtr<nsIFile> crashFile = MOZ_TRY(GetIncompleteStartupFile(mProfLD))__extension__({ auto mozTryVarTempResult = ::mozilla::ToResult
(GetIncompleteStartupFile(mProfLD)); if ((__builtin_expect(!!
(mozTryVarTempResult.isErr()), 0))) { return mozTryVarTempResult
.propagateErr(); } mozTryVarTempResult.unwrap(); })
;
6771 crashFile->Remove(false);
6772 }
6773 return NS_OK;
6774 });
6775
6776 // startup
6777 result = XRE_mainStartup(&exit);
6778 if (result != 0 || exit) return result;
6779
6780 // Start the real application. We use |aInitJSContext = false| because
6781 // XRE_mainRun wants to initialize the JSContext after reading user prefs.
6782
6783 mScopedXPCOM = MakeUnique<ScopedXPCOMStartup>();
6784
6785 rv = mScopedXPCOM->Initialize(/* aInitJSContext = */ false);
6786 if (rv == NS_ERROR_OMNIJAR_CORRUPT) {
6787 if (XRE_IsParentProcess()
6788#ifdef MOZ_BACKGROUNDTASKS1
6789 && !mozilla::BackgroundTasks::IsBackgroundTaskMode()
6790#endif
6791 ) {
6792 Output(
6793 true,
6794 "The installation seems to be corrupt.\nPlease check your hardware "
6795 "and disk setup\nand/or re-install.\n");
6796 }
6797 MOZ_CRASH("NS_ERROR_OMNIJAR_CORRUPT")do { do { } while (false); MOZ_ReportCrash("" "NS_ERROR_OMNIJAR_CORRUPT"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6797); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_ERROR_OMNIJAR_CORRUPT" ")"); do { MOZ_CrashSequence
(__null, 6797); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
6798 }
6799 NS_ENSURE_SUCCESS(rv, 1)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "1", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6799); return 1; } } while (false)
;
6800
6801 // run!
6802 rv = XRE_mainRun();
6803 if (rv == NS_ERROR_OMNIJAR_OR_DIR_MISSING) {
6804 if (XRE_IsParentProcess()
6805#ifdef MOZ_BACKGROUNDTASKS1
6806 && !mozilla::BackgroundTasks::IsBackgroundTaskMode()
6807#endif
6808 ) {
6809 Output(true,
6810 "The installation seems to be incomplete.\nPlease check your "
6811 "hardware and disk setup\nand/or re-install.\n");
6812 }
6813 if (mozilla::IsPackagedBuild()) {
6814 // IsPackagedBuild just looks for omni.ja on disk. If we were able to
6815 // find and open it before but not to load the expected JS module from
6816 // it now, signal corruption.
6817 MOZ_CRASH("NS_ERROR_OMNIJAR_CORRUPT")do { do { } while (false); MOZ_ReportCrash("" "NS_ERROR_OMNIJAR_CORRUPT"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6817); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_ERROR_OMNIJAR_CORRUPT" ")"); do { MOZ_CrashSequence
(__null, 6817); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
6818 }
6819 MOZ_CRASH("NS_ERROR_OMNIJAR_OR_DIR_MISSING")do { do { } while (false); MOZ_ReportCrash("" "NS_ERROR_OMNIJAR_OR_DIR_MISSING"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 6819); AnnotateMozCrashReason
("MOZ_CRASH(" "NS_ERROR_OMNIJAR_OR_DIR_MISSING" ")"); do { MOZ_CrashSequence
(__null, 6819); __attribute__((nomerge)) ::abort(); } while (
false); } while (false)
;
6820 }
6821
6822#ifdef MOZ_X111
6823 XRE_CleanupX11ErrorHandler();
6824#endif
6825
6826 gAbsoluteArgv0Path.Truncate();
6827
6828#if defined(MOZ_HAS_REMOTE1)
6829 // Shut down the remote service. We must do this before calling LaunchChild
6830 // if we're restarting because otherwise the new instance will attempt to
6831 // remote to this instance.
6832 if (gRemoteService) {
6833 gRemoteService->ShutdownServer();
6834 gStartupLock = nullptr;
6835 gRemoteService = nullptr;
6836 }
6837#endif
6838
6839 mScopedXPCOM = nullptr;
6840
6841 // unlock the profile after ScopedXPCOMStartup object (xpcom)
6842 // has gone out of scope. see bug #386739 for more details
6843 mProfileLock->Unlock();
6844 gProfileLock = nullptr;
6845
6846 gLastAppVersion.Truncate();
6847 gLastAppBuildID.Truncate();
6848
6849#ifdef MOZ_WIDGET_GTK1
6850 // gdk_display_close also calls gdk_display_manager_set_default_display
6851 // appropriately when necessary.
6852 if (!gfxPlatform::IsHeadless()) {
6853# ifdef MOZ_WAYLAND1
6854 WaylandDisplayRelease();
6855 gWaylandProxy = nullptr;
6856# endif
6857 }
6858#endif
6859
6860 mozilla::AppShutdown::MaybeDoRestart();
6861
6862 XRE_DeinitCommandLine();
6863
6864 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
6865 return 1;
6866 }
6867 return mozilla::AppShutdown::GetExitCode();
6868}
6869
6870void XRE_StopLateWriteChecks(void) { mozilla::StopLateWriteChecks(); }
6871
6872int XRE_main(int argc, char* argv[], const BootstrapConfig& aConfig) {
6873 XREMain main;
6874
6875 int result = main.XRE_main(argc, argv, aConfig);
6876 mozilla::RecordShutdownEndTimeStamp();
6877#ifdef MOZ_BACKGROUNDTASKS1
6878 // This is well after the profile has been unlocked, so it's okay if this does
6879 // delete this background task's temporary profile.
6880 mozilla::BackgroundTasks::Shutdown();
6881#endif
6882 return result;
6883}
6884
6885nsresult XRE_InitCommandLine(int aArgc, char* aArgv[]) {
6886 nsresult rv = NS_OK;
6887
6888#if defined(XP_WIN)
6889 CommandLine::Init(aArgc, aArgv);
6890#else
6891
6892 // these leak on error, but that's OK: we'll just exit()
6893 char** canonArgs = new char*[aArgc];
6894
6895 // get the canonical version of the binary's path
6896 nsCOMPtr<nsIFile> binFile;
6897 rv = XRE_GetBinaryPath(getter_AddRefs(binFile));
6898 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return NS_ERROR_FAILURE;
6899
6900 nsAutoCString canonBinPath;
6901 rv = binFile->GetNativePath(canonBinPath);
6902 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return NS_ERROR_FAILURE;
6903
6904 canonArgs[0] = strdup(canonBinPath.get());
6905
6906 for (int i = 1; i < aArgc; ++i) {
6907 if (aArgv[i]) {
6908 canonArgs[i] = strdup(aArgv[i]);
6909 }
6910 }
6911
6912 NS_ASSERTION(!CommandLine::IsInitialized(), "Bad news!")do { if (!(!CommandLine::IsInitialized())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Bad news!", "!CommandLine::IsInitialized()", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6912); MOZ_PretendNoReturn(); } } while (0)
;
6913 CommandLine::Init(aArgc, canonArgs);
6914
6915 for (int i = 0; i < aArgc; ++i) free(canonArgs[i]);
6916 delete[] canonArgs;
6917#endif
6918
6919#if defined(MOZ_WIDGET_ANDROID)
6920 // gAppData is non-null iff this is the parent process. Otherwise,
6921 // the `-greomni`/`-appomni` flags are cross-platform and handled in
6922 // ContentProcess::Init.
6923 if (gAppData) {
6924 nsCOMPtr<nsIFile> greOmni = gAppData->xreDirectory;
6925 if (!greOmni) {
6926 return NS_ERROR_FAILURE;
6927 }
6928 mozilla::Omnijar::Init(greOmni, greOmni);
6929 MOZ_RELEASE_ASSERT(IsPackagedBuild(), "Android builds are always packaged")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsPackagedBuild())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsPackagedBuild()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsPackagedBuild()"
" (" "Android builds are always packaged" ")", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6929); AnnotateMozCrashReason("MOZ_RELEASE_ASSERT" "(" "IsPackagedBuild()"
") (" "Android builds are always packaged" ")"); do { MOZ_CrashSequence
(__null, 6929); __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
6930 }
6931#endif
6932
6933 return rv;
6934}
6935
6936nsresult XRE_DeinitCommandLine() {
6937 nsresult rv = NS_OK;
6938
6939 CommandLine::Terminate();
6940
6941 return rv;
6942}
6943
6944GeckoProcessType XRE_GetProcessType() { return GetGeckoProcessType(); }
6945
6946const char* XRE_GetProcessTypeString() {
6947 return XRE_GeckoProcessTypeToString(XRE_GetProcessType());
6948}
6949
6950GeckoChildID XRE_GetChildID() { return GetGeckoChildID(); }
6951
6952bool XRE_IsE10sParentProcess() {
6953#ifdef MOZ_WIDGET_ANDROID
6954 return XRE_IsParentProcess() && BrowserTabsRemoteAutostart() &&
6955 mozilla::jni::IsAvailable();
6956#else
6957 return XRE_IsParentProcess() && BrowserTabsRemoteAutostart();
6958#endif
6959}
6960
6961#define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, proc_typename, \
6962 process_bin_type, procinfo_typename, \
6963 webidl_typename, allcaps_name) \
6964 bool XRE_Is##proc_typename##Process() { \
6965 return XRE_GetProcessType() == GeckoProcessType_##enum_name; \
6966 }
6967#include "mozilla/GeckoProcessTypes.inc"
6968#undef GECKO_PROCESS_TYPE
6969
6970bool XRE_UseNativeEventProcessing() {
6971#if defined(XP_WIN)
6972 // If win32k is locked down we can't use native event processing.
6973 if (IsWin32kLockedDown()) {
6974 return false;
6975 }
6976#endif
6977
6978 switch (XRE_GetProcessType()) {
6979#if defined(XP_DARWIN) || defined(XP_WIN)
6980 case GeckoProcessType_RDD:
6981 case GeckoProcessType_Socket:
6982 return false;
6983 case GeckoProcessType_Utility: {
6984# if defined(XP_WIN)
6985 auto upc = mozilla::ipc::UtilityProcessChild::Get();
6986 MOZ_ASSERT(upc)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(upc)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(upc))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("upc", "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp"
, 6986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "upc" ")"); do
{ MOZ_CrashSequence(__null, 6986); __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
6987
6988 using SboxKind = mozilla::ipc::SandboxingKind;
6989 // These processes are used as external hosts for accessing Windows
6990 // APIs which (may) require a Windows native event loop.
6991 return upc->mSandbox == SboxKind::WINDOWS_UTILS ||
6992 upc->mSandbox == SboxKind::WINDOWS_FILE_DIALOG;
6993# else
6994 return false;
6995# endif // defined(XP_WIN)
6996 }
6997#endif // defined(XP_DARWIN) || defined(XP_WIN)
6998 case GeckoProcessType_GMPlugin:
6999 return mozilla::gmp::GMPProcessChild::UseNativeEventProcessing();
7000 case GeckoProcessType_Content:
7001#if defined(XP_DARWIN)
7002 return false;
7003#else
7004 return StaticPrefs::dom_ipc_useNativeEventProcessing_content();
7005#endif // defined (XP_DARWIN)
7006 default:
7007 return true;
7008 }
7009}
7010
7011namespace mozilla {
7012
7013uint32_t GetMaxWebProcessCount() {
7014 // multiOptOut is in int to allow us to run multiple experiments without
7015 // introducing multiple prefs a la the autostart.N prefs.
7016 if (Preferences::GetInt("dom.ipc.multiOptOut", 0) >=
7017 nsIXULRuntime::E10S_MULTI_EXPERIMENT) {
7018 return 1;
7019 }
7020
7021 const char* optInPref = "dom.ipc.processCount";
7022 uint32_t optInPrefValue = Preferences::GetInt(optInPref, 1);
7023 return std::max(1u, optInPrefValue);
7024}
7025
7026const char* PlatformBuildID() { return gToolkitBuildID; }
7027
7028} // namespace mozilla
7029
7030void SetupErrorHandling(const char* progname) {
7031#ifdef XP_WIN
7032 /* On Windows XPSP3 and Windows Vista if DEP is configured off-by-default
7033 we still want DEP protection: enable it explicitly and programmatically.
7034
7035 This function is not available on WinXPSP2 so we dynamically load it.
7036 */
7037
7038 HMODULE kernel32 = GetModuleHandleW(L"kernel32.dll");
7039 SetProcessDEPPolicyFunc _SetProcessDEPPolicy =
7040 (SetProcessDEPPolicyFunc)GetProcAddress(kernel32, "SetProcessDEPPolicy");
7041 if (_SetProcessDEPPolicy) _SetProcessDEPPolicy(PROCESS_DEP_ENABLE);
7042
7043 // Suppress the "DLL Foo could not be found" dialog, such that if dependent
7044 // libraries (such as GDI+) are not preset, we gracefully fail to load those
7045 // XPCOM components, instead of being ungraceful.
7046 UINT realMode = SetErrorMode(0);
7047 realMode |= SEM_FAILCRITICALERRORS;
7048 // If XRE_NO_WINDOWS_CRASH_DIALOG is set, suppress displaying the "This
7049 // application has crashed" dialog box. This is mainly useful for
7050 // automated testing environments, e.g. tinderbox, where there's no need
7051 // for a dozen of the dialog boxes to litter the console
7052 if (getenv("XRE_NO_WINDOWS_CRASH_DIALOG"))
7053 realMode |= SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX;
7054
7055 SetErrorMode(realMode);
7056
7057#endif
7058
7059 InstallSignalHandlers(progname);
7060
7061 // Unbuffer stdout, needed for tinderbox tests.
7062 setbuf(stdoutstdout, nullptr);
7063}
7064
7065static bool gRunSelfAsContentProc = false;
7066
7067void XRE_EnableSameExecutableForContentProc() {
7068 if (!PR_GetEnv("MOZ_SEPARATE_CHILD_PROCESS")) {
7069 gRunSelfAsContentProc = true;
7070 }
7071}
7072
7073mozilla::BinPathType XRE_GetChildProcBinPathType(
7074 GeckoProcessType aProcessType) {
7075 MOZ_ASSERT(aProcessType != GeckoProcessType_Default)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aProcessType != GeckoProcessType_Default)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aProcessType != GeckoProcessType_Default))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aProcessType != GeckoProcessType_Default"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 7075); AnnotateMozCrashReason
("MOZ_ASSERT" "(" "aProcessType != GeckoProcessType_Default" ")"
); do { MOZ_CrashSequence(__null, 7075); __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7076
7077 if (!gRunSelfAsContentProc) {
7078 return BinPathType::PluginContainer;
7079 }
7080
7081#ifdef XP_WIN
7082 // Removing this pref and always using the parent binary, along with other
7083 // related clean up work, is tracked in Bug 2014843.
7084 if (StaticPrefs::dom_ipc_alwaysUseParentBinary()) {
7085 return BinPathType::Self;
7086 }
7087
7088 // On Windows, plugin-container may or may not be used depending on
7089 // the process type (e.g., actual plugins vs. content processes)
7090 switch (aProcessType) {
7091# define GECKO_PROCESS_TYPE(enum_value, enum_name, string_name, \
7092 proc_typename, process_bin_type, \
7093 procinfo_typename, webidl_typename, allcaps_name) \
7094 case GeckoProcessType_##enum_name: \
7095 return BinPathType::process_bin_type;
7096# include "mozilla/GeckoProcessTypes.inc"
7097# undef GECKO_PROCESS_TYPE
7098 default:
7099 return BinPathType::PluginContainer;
7100 }
7101#else
7102 // On (non-macOS) Unix, plugin-container isn't used (except in cases
7103 // like xpcshell that are handled by the gRunSelfAsContentProc check
7104 // above). It isn't necessary the way it is on other platforms, and
7105 // it interferes with using the fork server.
7106 return BinPathType::Self;
7107#endif
7108}
7109
7110// From mozglue/static/rust/lib.rs
7111extern "C" void install_rust_hooks();
7112
7113struct InstallRustHooks {
7114 InstallRustHooks() { install_rust_hooks(); }
7115};
7116
7117MOZ_RUNINIT InstallRustHooks sInstallRustHooks;
7118
7119#ifdef MOZ_ASAN_REPORTER
7120void setASanReporterPath(nsIFile* aDir) {
7121 nsCOMPtr<nsIFile> dir;
7122 aDir->Clone(getter_AddRefs(dir));
7123
7124 dir->Append(u"asan"_ns);
7125 nsresult rv = dir->Create(nsIFile::DIRECTORY_TYPE, 0700);
7126 if (NS_WARN_IF(NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS)NS_warn_if_impl(((bool)(__builtin_expect(!!(NS_FAILED_impl(rv
)), 0))) && rv != NS_ERROR_FILE_ALREADY_EXISTS, "NS_FAILED(rv) && rv != NS_ERROR_FILE_ALREADY_EXISTS"
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 7126)
) {
7127 MOZ_CRASH("[ASan Reporter] Unable to create crash directory.")do { do { } while (false); MOZ_ReportCrash("" "[ASan Reporter] Unable to create crash directory."
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 7127); AnnotateMozCrashReason
("MOZ_CRASH(" "[ASan Reporter] Unable to create crash directory."
")"); do { MOZ_CrashSequence(__null, 7127); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
7128 }
7129
7130 dir->Append(u"ff_asan_log"_ns);
7131
7132# ifdef XP_WIN
7133 nsAutoString nspathW;
7134 rv = dir->GetPath(nspathW);
7135 NS_ConvertUTF16toUTF8 nspath(nspathW);
7136# else
7137 nsAutoCString nspath;
7138 rv = dir->GetNativePath(nspath);
7139# endif
7140 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
7141 MOZ_CRASH("[ASan Reporter] Unable to get native path for crash directory.")do { do { } while (false); MOZ_ReportCrash("" "[ASan Reporter] Unable to get native path for crash directory."
, "/root/firefox-clang/toolkit/xre/nsAppRunner.cpp", 7141); AnnotateMozCrashReason
("MOZ_CRASH(" "[ASan Reporter] Unable to get native path for crash directory."
")"); do { MOZ_CrashSequence(__null, 7141); __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
7142 }
7143
7144 __sanitizer_set_report_path(nspath.get());
7145}
7146#endif

←

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/UniquePtr.h

→
1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5/* Smart pointer managing sole ownership of a resource. */
6
7#ifndef mozilla_UniquePtr_h
8#define mozilla_UniquePtr_h
9
10#include <memory>
11#include <utility>
12
13#include "mozilla/Attributes.h"
14
15namespace mozilla {
16
17template <typename T>
18using DefaultDelete = std::default_delete<T>;
19
20template <typename T, class D = DefaultDelete<T>>
21using UniquePtr = std::unique_ptr<T, D>;
22
23} // namespace mozilla
24
25namespace mozilla {
26
27namespace detail {
28
29template <typename T>
30struct UniqueSelector {
31 typedef UniquePtr<T> SingleObject;
32};
33
34template <typename T>
35struct UniqueSelector<T[]> {
36 typedef UniquePtr<T[]> UnknownBound;
37};
38
39template <typename T, decltype(sizeof(int)) N>
40struct UniqueSelector<T[N]> {
41 typedef UniquePtr<T[N]> KnownBound;
42};
43
44} // namespace detail
45
46/**
47 * MakeUnique is a helper function for allocating new'd objects and arrays,
48 * returning a UniquePtr containing the resulting pointer. The semantics of
49 * MakeUnique<Type>(...) are as follows.
50 *
51 * If Type is an array T[n]:
52 * Disallowed, deleted, no overload for you!
53 * If Type is an array T[]:
54 * MakeUnique<T[]>(size_t) is the only valid overload. The pointer returned
55 * is as if by |new T[n]()|, which value-initializes each element. (If T
56 * isn't a class type, this will zero each element. If T is a class type,
57 * then roughly speaking, each element will be constructed using its default
58 * constructor. See C++11 [dcl.init]p7 for the full gory details.)
59 * If Type is non-array T:
60 * The arguments passed to MakeUnique<T>(...) are forwarded into a
61 * |new T(...)| call, initializing the T as would happen if executing
62 * |T(...)|.
63 *
64 * There are various benefits to using MakeUnique instead of |new| expressions.
65 *
66 * First, MakeUnique eliminates use of |new| from code entirely. If objects are
67 * only created through UniquePtr, then (assuming all explicit release() calls
68 * are safe, including transitively, and no type-safety casting funniness)
69 * correctly maintained ownership of the UniquePtr guarantees no leaks are
70 * possible. (This pays off best if a class is only ever created through a
71 * factory method on the class, using a private constructor.)
72 *
73 * Second, initializing a UniquePtr using a |new| expression requires repeating
74 * the name of the new'd type, whereas MakeUnique in concert with the |auto|
75 * keyword names it only once:
76 *
77 * UniquePtr<char> ptr1(new char()); // repetitive
78 * auto ptr2 = MakeUnique<char>(); // shorter
79 *
80 * Of course this assumes the reader understands the operation MakeUnique
81 * performs. In the long run this is probably a reasonable assumption. In the
82 * short run you'll have to use your judgment about what readers can be expected
83 * to know, or to quickly look up.
84 *
85 * Third, a call to MakeUnique can be assigned directly to a UniquePtr. In
86 * contrast you can't assign a pointer into a UniquePtr without using the
87 * cumbersome reset().
88 *
89 * UniquePtr<char> p;
90 * p = new char; // ERROR
91 * p.reset(new char); // works, but fugly
92 * p = MakeUnique<char>(); // preferred
93 *
94 * (And third, although not relevant to Mozilla: MakeUnique is exception-safe.
95 * An exception thrown after |new T| succeeds will leak that memory, unless the
96 * pointer is assigned to an object that will manage its ownership. UniquePtr
97 * ably serves this function.)
98 */
99
100template <typename T, typename... Args>
101auto MakeUnique(Args&&... aArgs) {
102 return std::make_unique<T>(std::forward<Args>(aArgs)...);
8
Calling 'make_unique<unsigned char[]>'
103}
104
105/**
106 * WrapUnique is a helper function to transfer ownership from a raw pointer
107 * into a UniquePtr<T>. It can only be used with a single non-array type.
108 *
109 * It is generally used this way:
110 *
111 * auto p = WrapUnique(new char);
112 *
113 * It can be used when MakeUnique is not usable, for example, when the
114 * constructor you are using is private, or you want to use aggregate
115 * initialization.
116 */
117
118template <typename T>
119typename detail::UniqueSelector<T>::SingleObject WrapUnique(T* aPtr) {
120 return UniquePtr<T>(aPtr);
121}
122
123} // namespace mozilla
124
125/**
126TempPtrToSetter(UniquePtr<T>*) -> T**-ish
127TempPtrToSetter(std::unique_ptr<T>*) -> T**-ish
128
129Make a temporary class to support assigning to UniquePtr/unique_ptr via passing
130a pointer to the callee.
131
132Often, APIs will be shaped like this trivial example:
133```
134nsresult Foo::NewChildBar(Bar** out) {
135 if (!IsOk()) return NS_ERROR_FAILURE;
136 *out = new Bar(this);
137 return NS_OK;
138}
139```
140
141In order to make this work with unique ptrs, it's often either risky or
142overwrought:
143```
144Bar* bar = nullptr;
145const auto cleanup = MakeScopeExit([&]() {
146 if (bar) {
147 delete bar;
148 }
149});
150if (FAILED(foo->NewChildBar(&bar)) {
151 // handle it
152}
153```
154
155```
156UniquePtr<Bar> bar;
157{
158 Bar* raw = nullptr;
159 const auto res = foo->NewChildBar(&bar);
160 bar.reset(raw);
161 if (FAILED(res) {
162 // handle it
163 }
164}
165```
166TempPtrToSettable is a shorthand for the latter approach, allowing something
167cleaner but also safe:
168
169```
170UniquePtr<Bar> bar;
171if (FAILED(foo->NewChildBar(TempPtrToSetter(&bar))) {
172 // handle it
173}
174```
175*/
176
177namespace mozilla {
178namespace detail {
179
180template <class T, class UniquePtrT>
181class MOZ_TEMPORARY_CLASS TempPtrToSetterT final {
182 private:
183 UniquePtrT* const mDest;
184 T* mNewVal;
185
186 public:
187 explicit TempPtrToSetterT(UniquePtrT* dest)
188 : mDest(dest), mNewVal(mDest->get()) {}
189
190 operator T**() { return &mNewVal; }
191
192 ~TempPtrToSetterT() {
193 if (mDest->get() != mNewVal) {
194 mDest->reset(mNewVal);
195 }
196 }
197};
198
199} // namespace detail
200
201template <class T, class Deleter>
202auto TempPtrToSetter(UniquePtr<T, Deleter>* const p) {
203 return detail::TempPtrToSetterT<T, UniquePtr<T, Deleter>>{p};
204}
205
206} // namespace mozilla
207
208namespace std {
209
210// No operator<, operator>, operator<=, operator>= for now because simplicity.
211
212template <typename T, class D>
213bool operator==(const mozilla::UniquePtr<T, D>& aX, const T* aY) {
214 return aX.get() == aY;
215}
216
217template <typename T, class D>
218bool operator==(const T* aY, const mozilla::UniquePtr<T, D>& aX) {
219 return aY == aX.get();
220}
221
222template <typename T, class D>
223bool operator!=(const mozilla::UniquePtr<T, D>& aX, const T* aY) {
224 return aX.get() != aY;
225}
226
227template <typename T, class D>
228bool operator!=(const T* aY, const mozilla::UniquePtr<T, D>& aX) {
229 return aY != aX.get();
230}
231} // namespace std
232
233#endif /* mozilla_UniquePtr_h */

←

/usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/bits/unique_ptr.h

→
1// unique_ptr implementation -*- C++ -*-
2
3// Copyright (C) 2008-2026 Free Software Foundation, Inc.
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 3, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// Under Section 7 of GPL version 3, you are granted additional
17// permissions described in the GCC Runtime Library Exception, version
18// 3.1, as published by the Free Software Foundation.
19
20// You should have received a copy of the GNU General Public License and
21// a copy of the GCC Runtime Library Exception along with this program;
22// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23// <http://www.gnu.org/licenses/>.
24
25/** @file bits/unique_ptr.h
26 * This is an internal header file, included by other library headers.
27 * Do not attempt to use it directly. @headername{memory}
28 */
29
30#ifndef _UNIQUE_PTR_H1
31#define _UNIQUE_PTR_H1 1
32
33#include <bits/c++config.h>
34#include <debug/assertions.h>
35#include <type_traits>
36#include <tuple>
37#include <bits/stl_function.h>
38#include <bits/functional_hash.h>
39#if __cplusplus202002L >= 202002L
40# include <compare>
41# if _GLIBCXX_HOSTED1
42# include <bits/ostream.h>
43# endif
44#endif
45
46namespace std _GLIBCXX_VISIBILITY(default)__attribute__ ((__visibility__ ("default")))
47{
48_GLIBCXX_BEGIN_NAMESPACE_VERSION
49
50 /**
51 * @addtogroup pointer_abstractions
52 * @{
53 */
54
55#if _GLIBCXX_USE_DEPRECATED1
56#pragma GCC diagnostic push
57#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
58 template<typename> class auto_ptr;
59#pragma GCC diagnostic pop
60#endif
61
62 /** Primary template of default_delete, used by unique_ptr for single objects
63 *
64 * @headerfile memory
65 * @since C++11
66 */
67 template<typename _Tp>
68 struct default_delete
69 {
70 /// Default constructor
71 constexpr default_delete() noexcept = default;
72
73 /** @brief Converting constructor.
74 *
75 * Allows conversion from a deleter for objects of another type, `_Up`,
76 * only if `_Up*` is convertible to `_Tp*`.
77 */
78 template<typename _Up,
79 typename = _Require<is_convertible<_Up*, _Tp*>>>
80 _GLIBCXX23_CONSTEXPR
81 default_delete(const default_delete<_Up>&) noexcept { }
82
83 /// Calls `delete __ptr`
84 _GLIBCXX23_CONSTEXPR
85 void
86 operator()(_Tp* __ptr) const
87 {
88 static_assert(!is_void<_Tp>::value,
89 "can't delete pointer to incomplete type");
90 static_assert(sizeof(_Tp)>0,
91 "can't delete pointer to incomplete type");
92 delete __ptr;
93 }
94 };
95
96 // _GLIBCXX_RESOLVE_LIB_DEFECTS
97 // DR 740 - omit specialization for array objects with a compile time length
98
99 /** Specialization of default_delete for arrays, used by `unique_ptr<T[]>`
100 *
101 * @headerfile memory
102 * @since C++11
103 */
104 template<typename _Tp>
105 struct default_delete<_Tp[]>
106 {
107 public:
108 /// Default constructor
109 constexpr default_delete() noexcept = default;
110
111 /** @brief Converting constructor.
112 *
113 * Allows conversion from a deleter for arrays of another type, such as
114 * a const-qualified version of `_Tp`.
115 *
116 * Conversions from types derived from `_Tp` are not allowed because
117 * it is undefined to `delete[]` an array of derived types through a
118 * pointer to the base type.
119 */
120 template<typename _Up,
121 typename = _Require<is_convertible<_Up(*)[], _Tp(*)[]>>>
122 _GLIBCXX23_CONSTEXPR
123 default_delete(const default_delete<_Up[]>&) noexcept { }
124
125 /// Calls `delete[] __ptr`
126 template<typename _Up>
127 _GLIBCXX23_CONSTEXPR
128 typename enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value>::type
129 operator()(_Up* __ptr) const
130 {
131 static_assert(sizeof(_Tp)>0,
132 "can't delete pointer to incomplete type");
133 delete [] __ptr;
134 }
135 };
136
137 /// @cond undocumented
138
139 // Manages the pointer and deleter of a unique_ptr
140 template <typename _Tp, typename _Dp>
141 class __uniq_ptr_impl
142 {
143 template <typename _Up, typename _Ep, typename = void>
144 struct _Ptr
145 {
146 using type = _Up*;
147 };
148
149 template <typename _Up, typename _Ep>
150 struct
151 _Ptr<_Up, _Ep, __void_t<typename remove_reference<_Ep>::type::pointer>>
152 {
153 using type = typename remove_reference<_Ep>::type::pointer;
154 };
155
156 public:
157 using _DeleterConstraint = enable_if<
158 __and_<__not_<is_pointer<_Dp>>,
159 is_default_constructible<_Dp>>::value>;
160
161 using pointer = typename _Ptr<_Tp, _Dp>::type;
162
163 static_assert( !is_rvalue_reference<_Dp>::value,
164 "unique_ptr's deleter type must be a function object type"
165 " or an lvalue reference type" );
166
167 __uniq_ptr_impl() = default;
168 _GLIBCXX23_CONSTEXPR
169 __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; }
170
171 template<typename _Del>
172 _GLIBCXX23_CONSTEXPR
173 __uniq_ptr_impl(pointer __p, _Del&& __d)
174 : _M_t(__p, std::forward<_Del>(__d)) { }
175
176 _GLIBCXX23_CONSTEXPR
177 __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept
178 : _M_t(std::move(__u._M_t))
179 { __u._M_ptr() = nullptr; }
180
181 _GLIBCXX23_CONSTEXPR
182 __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept
183 {
184 reset(__u.release());
185 _M_deleter() = std::forward<_Dp>(__u._M_deleter());
186 return *this;
187 }
188
189 _GLIBCXX23_CONSTEXPR
190 pointer& _M_ptr() noexcept { return std::get<0>(_M_t); }
191 _GLIBCXX23_CONSTEXPR
192 pointer _M_ptr() const noexcept { return std::get<0>(_M_t); }
193 _GLIBCXX23_CONSTEXPR
194 _Dp& _M_deleter() noexcept { return std::get<1>(_M_t); }
195 _GLIBCXX23_CONSTEXPR
196 const _Dp& _M_deleter() const noexcept { return std::get<1>(_M_t); }
197
198 _GLIBCXX23_CONSTEXPR
199 void reset(pointer __p) noexcept
200 {
201 const pointer __old_p = _M_ptr();
202 _M_ptr() = __p;
203 if (__old_p)
204 _M_deleter()(__old_p);
205 }
206
207 _GLIBCXX23_CONSTEXPR
208 pointer release() noexcept
209 {
210 pointer __p = _M_ptr();
211 _M_ptr() = nullptr;
212 return __p;
213 }
214
215 _GLIBCXX23_CONSTEXPR
216 void
217 swap(__uniq_ptr_impl& __rhs) noexcept
218 {
219 using std::swap;
220 swap(this->_M_ptr(), __rhs._M_ptr());
221 swap(this->_M_deleter(), __rhs._M_deleter());
222 }
223
224 private:
225 tuple<pointer, _Dp> _M_t;
226 };
227
228 // Defines move construction + assignment as either defaulted or deleted.
229 template <typename _Tp, typename _Dp,
230 bool = is_move_constructible<_Dp>::value,
231 bool = is_move_assignable<_Dp>::value>
232 struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp>
233 {
234 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
235 __uniq_ptr_data(__uniq_ptr_data&&) = default;
236 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
237 };
238
239 template <typename _Tp, typename _Dp>
240 struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp>
241 {
242 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
243 __uniq_ptr_data(__uniq_ptr_data&&) = default;
244 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
245 };
246
247 template <typename _Tp, typename _Dp>
248 struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp>
249 {
250 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
251 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
252 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default;
253 };
254
255 template <typename _Tp, typename _Dp>
256 struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp>
257 {
258 using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl;
259 __uniq_ptr_data(__uniq_ptr_data&&) = delete;
260 __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete;
261 };
262 /// @endcond
263
264 // 20.7.1.2 unique_ptr for single objects.
265
266 /// A move-only smart pointer that manages unique ownership of a resource.
267 /// @headerfile memory
268 /// @since C++11
269 template <typename _Tp, typename _Dp = default_delete<_Tp>>
270 class unique_ptr
271 {
272 template <typename _Up>
273 using _DeleterConstraint =
274 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
275
276 __uniq_ptr_data<_Tp, _Dp> _M_t;
277
278 public:
279 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
280 using element_type = _Tp;
281 using deleter_type = _Dp;
282
283 private:
284 // helper template for detecting a safe conversion from another
285 // unique_ptr
286 template<typename _Up, typename _Ep>
287 using __safe_conversion_up = __and_<
288 is_convertible<typename unique_ptr<_Up, _Ep>::pointer, pointer>,
289 __not_<is_array<_Up>>
290 >;
291
292#if ! __cpp_concepts202002
293 template<typename _Ptr, typename = void>
294 struct _Nothrow_deref
295 : false_type { };
296
297 template<typename _Ptr>
298 struct _Nothrow_deref<_Ptr, __void_t<decltype(*std::declval<_Ptr>())>>
299 : __bool_constant<noexcept(*std::declval<_Ptr>())> { };
300#endif
301
302 public:
303 // Constructors.
304
305 /// Default constructor, creates a unique_ptr that owns nothing.
306 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
307 constexpr unique_ptr() noexcept
308 : _M_t()
309 { }
310
311 /** Takes ownership of a pointer.
312 *
313 * @param __p A pointer to an object of @c element_type
314 *
315 * The deleter will be value-initialized.
316 */
317 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
318 _GLIBCXX23_CONSTEXPR
319 explicit
320 unique_ptr(pointer __p) noexcept
321 : _M_t(__p)
322 { }
323
324 /** Takes ownership of a pointer.
325 *
326 * @param __p A pointer to an object of @c element_type
327 * @param __d A reference to a deleter.
328 *
329 * The deleter will be initialized with @p __d
330 */
331 template<typename _Del = deleter_type,
332 typename = _Require<is_copy_constructible<_Del>>>
333 _GLIBCXX23_CONSTEXPR
334 unique_ptr(pointer __p, const deleter_type& __d) noexcept
335 : _M_t(__p, __d) { }
336
337 /** Takes ownership of a pointer.
338 *
339 * @param __p A pointer to an object of @c element_type
340 * @param __d An rvalue reference to a (non-reference) deleter.
341 *
342 * The deleter will be initialized with @p std::move(__d)
343 */
344 template<typename _Del = deleter_type,
345 typename = _Require<is_move_constructible<_Del>>>
346 _GLIBCXX23_CONSTEXPR
347 unique_ptr(pointer __p,
348 __enable_if_t<!is_lvalue_reference<_Del>::value,
349 _Del&&> __d) noexcept
350 : _M_t(__p, std::move(__d))
351 { }
352
353 template<typename _Del = deleter_type,
354 typename _DelUnref = typename remove_reference<_Del>::type>
355 _GLIBCXX23_CONSTEXPR
356 unique_ptr(pointer,
357 __enable_if_t<is_lvalue_reference<_Del>::value,
358 _DelUnref&&>) = delete;
359
360 /// Creates a unique_ptr that owns nothing.
361 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
362 constexpr unique_ptr(nullptr_t) noexcept
363 : _M_t()
364 { }
365
366 // Move constructors.
367
368 /// Move constructor.
369 unique_ptr(unique_ptr&&) = default;
370
371 /** @brief Converting constructor from another type
372 *
373 * Requires that the pointer owned by @p __u is convertible to the
374 * type of pointer owned by this object, @p __u does not own an array,
375 * and @p __u has a compatible deleter type.
376 */
377 template<typename _Up, typename _Ep, typename = _Require<
378 __safe_conversion_up<_Up, _Ep>,
379 __conditional_t<is_reference<_Dp>::value,
380 is_same<_Ep, _Dp>,
381 is_convertible<_Ep, _Dp>>>>
382 _GLIBCXX23_CONSTEXPR
383 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
384 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
385 { }
386
387#if _GLIBCXX_USE_DEPRECATED1
388#pragma GCC diagnostic push
389#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
390 /// Converting constructor from @c auto_ptr
391 template<typename _Up,
392 typename = _Require<is_convertible<_Up*, pointer>,
393 is_same<_Dp, default_delete<_Tp>>>>
394 unique_ptr(auto_ptr<_Up>&& __u) noexcept;
395#pragma GCC diagnostic pop
396#endif
397
398 /// Destructor, invokes the deleter if the stored pointer is not null.
399#if __cplusplus202002L > 202002L && __cpp_constexpr_dynamic_alloc201907L
400 constexpr
401#endif
402 ~unique_ptr() noexcept
403 {
404 static_assert(__is_invocable<deleter_type&, pointer>::value,
405 "unique_ptr's deleter must be invocable with a pointer");
406 auto& __ptr = _M_t._M_ptr();
407 if (__ptr != nullptr)
408 get_deleter()(std::move(__ptr));
409 __ptr = pointer();
410 }
411
412 // Assignment.
413
414 /** @brief Move assignment operator.
415 *
416 * Invokes the deleter if this object owns a pointer.
417 */
418 unique_ptr& operator=(unique_ptr&&) = default;
419
420 /** @brief Assignment from another type.
421 *
422 * @param __u The object to transfer ownership from, which owns a
423 * convertible pointer to a non-array object.
424 *
425 * Invokes the deleter if this object owns a pointer.
426 */
427 template<typename _Up, typename _Ep>
428 _GLIBCXX23_CONSTEXPR
429 typename enable_if< __and_<
430 __safe_conversion_up<_Up, _Ep>,
431 is_assignable<deleter_type&, _Ep&&>
432 >::value,
433 unique_ptr&>::type
434 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
435 {
436 reset(__u.release());
437 get_deleter() = std::forward<_Ep>(__u.get_deleter());
438 return *this;
439 }
440
441 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
442 _GLIBCXX23_CONSTEXPR
443 unique_ptr&
444 operator=(nullptr_t) noexcept
445 {
446 reset();
447 return *this;
448 }
449
450 // Observers.
451
452 /// Dereference the stored pointer.
453 _GLIBCXX23_CONSTEXPR
454 typename add_lvalue_reference<element_type>::type
455 operator*() const
456 // _GLIBCXX_RESOLVE_LIB_DEFECTS
457 // 2762. unique_ptr operator*() should be noexcept
458 // 4324. unique_ptr<void>::operator* is not SFINAE-friendly
459#if __cpp_concepts202002
460 noexcept(noexcept(*std::declval<pointer>()))
461 requires requires { *std::declval<pointer>(); }
462#else
463 noexcept(_Nothrow_deref<pointer>::value)
464#endif
465 {
466#if _GLIBCXX_USE_BUILTIN_TRAIT(__reference_converts_from_temporary)(1 || ! 0)
467 // _GLIBCXX_RESOLVE_LIB_DEFECTS
468 // 4148. unique_ptr::operator* should not allow dangling references
469 using _ResT = typename add_lvalue_reference<element_type>::type;
470 using _DerefT = decltype(*get());
471 static_assert(!__reference_converts_from_temporary(_ResT, _DerefT),
472 "operator* must not return a dangling reference");
473#endif
474 __glibcxx_assert(get() != pointer())do { if (__builtin_expect(!bool(get() != pointer()), false)) std
::__glibcxx_assert_fail("/usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/bits/unique_ptr.h"
, 474, __PRETTY_FUNCTION__, "get() != pointer()"); } while (false
)
;
475 return *get();
476 }
477
478 /// Return the stored pointer.
479 _GLIBCXX23_CONSTEXPR
480 pointer
481 operator->() const noexcept
482 {
483 _GLIBCXX_DEBUG_PEDASSERT(get() != pointer());
484 return get();
485 }
486
487 /// Return the stored pointer.
488 _GLIBCXX23_CONSTEXPR
489 pointer
490 get() const noexcept
491 { return _M_t._M_ptr(); }
492
493 /// Return a reference to the stored deleter.
494 _GLIBCXX23_CONSTEXPR
495 deleter_type&
496 get_deleter() noexcept
497 { return _M_t._M_deleter(); }
498
499 /// Return a reference to the stored deleter.
500 _GLIBCXX23_CONSTEXPR
501 const deleter_type&
502 get_deleter() const noexcept
503 { return _M_t._M_deleter(); }
504
505 /// Return @c true if the stored pointer is not null.
506 _GLIBCXX23_CONSTEXPR
507 explicit operator bool() const noexcept
508 { return get() == pointer() ? false : true; }
509
510 // Modifiers.
511
512 /// Release ownership of any stored pointer.
513 _GLIBCXX23_CONSTEXPR
514 pointer
515 release() noexcept
516 { return _M_t.release(); }
517
518 /** @brief Replace the stored pointer.
519 *
520 * @param __p The new pointer to store.
521 *
522 * The deleter will be invoked if a pointer is already owned.
523 */
524 _GLIBCXX23_CONSTEXPR
525 void
526 reset(pointer __p = pointer()) noexcept
527 {
528 static_assert(__is_invocable<deleter_type&, pointer>::value,
529 "unique_ptr's deleter must be invocable with a pointer");
530 _M_t.reset(std::move(__p));
531 }
532
533 /// Exchange the pointer and deleter with another object.
534 _GLIBCXX23_CONSTEXPR
535 void
536 swap(unique_ptr& __u) noexcept
537 {
538 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
539 _M_t.swap(__u._M_t);
540 }
541
542 // Disable copy from lvalue.
543 unique_ptr(const unique_ptr&) = delete;
544 unique_ptr& operator=(const unique_ptr&) = delete;
545
546 private:
547#ifdef __glibcxx_out_ptr
548 template<typename, typename, typename...>
549 friend class out_ptr_t;
550 template<typename, typename, typename...>
551 friend class inout_ptr_t;
552#endif
553 };
554
555 // 20.7.1.3 unique_ptr for array objects with a runtime length
556 // [unique.ptr.runtime]
557 // _GLIBCXX_RESOLVE_LIB_DEFECTS
558 // DR 740 - omit specialization for array objects with a compile time length
559
560 /// A move-only smart pointer that manages unique ownership of an array.
561 /// @headerfile memory
562 /// @since C++11
563 template<typename _Tp, typename _Dp>
564 class unique_ptr<_Tp[], _Dp>
565 {
566 template <typename _Up>
567 using _DeleterConstraint =
568 typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type;
569
570 __uniq_ptr_data<_Tp, _Dp> _M_t;
571
572 // like is_base_of<_Tp, _Up> but false if unqualified types are the same
573 template<typename _Up>
574 using __is_derived_Tp
575 = __and_< is_base_of<_Tp, _Up>,
576 __not_<is_same<__remove_cv_t<_Tp>, __remove_cv_t<_Up>>> >;
577
578 public:
579 using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer;
580 using element_type = _Tp;
581 using deleter_type = _Dp;
582
583 // helper template for detecting a safe conversion from another
584 // unique_ptr
585 template<typename _Up, typename _Ep,
586 typename _UPtr = unique_ptr<_Up, _Ep>,
587 typename _UP_pointer = typename _UPtr::pointer,
588 typename _UP_element_type = typename _UPtr::element_type>
589 using __safe_conversion_up = __and_<
590 is_array<_Up>,
591 is_same<pointer, element_type*>,
592 is_same<_UP_pointer, _UP_element_type*>,
593 is_convertible<_UP_element_type(*)[], element_type(*)[]>
594 >;
595
596 // helper template for detecting a safe conversion from a raw pointer
597 template<typename _Up>
598 using __safe_conversion_raw = __and_<
599 __or_<__or_<is_same<_Up, pointer>,
600 is_same<_Up, nullptr_t>>,
601 __and_<is_pointer<_Up>,
602 is_same<pointer, element_type*>,
603 is_convertible<
604 typename remove_pointer<_Up>::type(*)[],
605 element_type(*)[]>
606 >
607 >
608 >;
609
610 // Constructors.
611
612 /// Default constructor, creates a unique_ptr that owns nothing.
613 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
614 constexpr unique_ptr() noexcept
615 : _M_t()
616 { }
617
618 /** Takes ownership of a pointer.
619 *
620 * @param __p A pointer to an array of a type safely convertible
621 * to an array of @c element_type
622 *
623 * The deleter will be value-initialized.
624 */
625 template<typename _Up,
626 typename _Vp = _Dp,
627 typename = _DeleterConstraint<_Vp>,
628 typename = typename enable_if<
629 __safe_conversion_raw<_Up>::value, bool>::type>
630 _GLIBCXX23_CONSTEXPR
631 explicit
632 unique_ptr(_Up __p) noexcept
633 : _M_t(__p)
634 { }
635
636 /** Takes ownership of a pointer.
637 *
638 * @param __p A pointer to an array of a type safely convertible
639 * to an array of @c element_type
640 * @param __d A reference to a deleter.
641 *
642 * The deleter will be initialized with @p __d
643 */
644 template<typename _Up, typename _Del = deleter_type,
645 typename = _Require<__safe_conversion_raw<_Up>,
646 is_copy_constructible<_Del>>>
647 _GLIBCXX23_CONSTEXPR
648 unique_ptr(_Up __p, const deleter_type& __d) noexcept
649 : _M_t(__p, __d) { }
650
651 /** Takes ownership of a pointer.
652 *
653 * @param __p A pointer to an array of a type safely convertible
654 * to an array of @c element_type
655 * @param __d A reference to a deleter.
656 *
657 * The deleter will be initialized with @p std::move(__d)
658 */
659 template<typename _Up, typename _Del = deleter_type,
660 typename = _Require<__safe_conversion_raw<_Up>,
661 is_move_constructible<_Del>>>
662 _GLIBCXX23_CONSTEXPR
663 unique_ptr(_Up __p,
664 __enable_if_t<!is_lvalue_reference<_Del>::value,
665 _Del&&> __d) noexcept
666 : _M_t(std::move(__p), std::move(__d))
667 { }
668
669 template<typename _Up, typename _Del = deleter_type,
670 typename _DelUnref = typename remove_reference<_Del>::type,
671 typename = _Require<__safe_conversion_raw<_Up>>>
672 unique_ptr(_Up,
673 __enable_if_t<is_lvalue_reference<_Del>::value,
674 _DelUnref&&>) = delete;
675
676 /// Move constructor.
677 unique_ptr(unique_ptr&&) = default;
678
679 /// Creates a unique_ptr that owns nothing.
680 template<typename _Del = _Dp, typename = _DeleterConstraint<_Del>>
681 constexpr unique_ptr(nullptr_t) noexcept
682 : _M_t()
683 { }
684
685 template<typename _Up, typename _Ep, typename = _Require<
686 __safe_conversion_up<_Up, _Ep>,
687 __conditional_t<is_reference<_Dp>::value,
688 is_same<_Ep, _Dp>,
689 is_convertible<_Ep, _Dp>>>>
690 _GLIBCXX23_CONSTEXPR
691 unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept
692 : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter()))
693 { }
694
695 /// Destructor, invokes the deleter if the stored pointer is not null.
696#if __cplusplus202002L > 202002L && __cpp_constexpr_dynamic_alloc201907L
697 constexpr
698#endif
699 ~unique_ptr()
700 {
701 auto& __ptr = _M_t._M_ptr();
702 if (__ptr != nullptr)
703 get_deleter()(__ptr);
704 __ptr = pointer();
705 }
706
707 // Assignment.
708
709 /** @brief Move assignment operator.
710 *
711 * Invokes the deleter if this object owns a pointer.
712 */
713 unique_ptr&
714 operator=(unique_ptr&&) = default;
715
716 /** @brief Assignment from another type.
717 *
718 * @param __u The object to transfer ownership from, which owns a
719 * convertible pointer to an array object.
720 *
721 * Invokes the deleter if this object owns a pointer.
722 */
723 template<typename _Up, typename _Ep>
724 _GLIBCXX23_CONSTEXPR
725 typename
726 enable_if<__and_<__safe_conversion_up<_Up, _Ep>,
727 is_assignable<deleter_type&, _Ep&&>
728 >::value,
729 unique_ptr&>::type
730 operator=(unique_ptr<_Up, _Ep>&& __u) noexcept
731 {
732 reset(__u.release());
733 get_deleter() = std::forward<_Ep>(__u.get_deleter());
734 return *this;
735 }
736
737 /// Reset the %unique_ptr to empty, invoking the deleter if necessary.
738 _GLIBCXX23_CONSTEXPR
739 unique_ptr&
740 operator=(nullptr_t) noexcept
741 {
742 reset();
743 return *this;
744 }
745
746 // Observers.
747
748 /// Access an element of owned array.
749 _GLIBCXX23_CONSTEXPR
750 typename std::add_lvalue_reference<element_type>::type
751 operator[](size_t __i) const
752 {
753 __glibcxx_assert(get() != pointer())do { if (__builtin_expect(!bool(get() != pointer()), false)) std
::__glibcxx_assert_fail("/usr/lib/gcc/x86_64-linux-gnu/16/../../../../include/c++/16/bits/unique_ptr.h"
, 753, __PRETTY_FUNCTION__, "get() != pointer()"); } while (false
)
;
754 return get()[__i];
755 }
756
757 /// Return the stored pointer.
758 _GLIBCXX23_CONSTEXPR
759 pointer
760 get() const noexcept
761 { return _M_t._M_ptr(); }
762
763 /// Return a reference to the stored deleter.
764 _GLIBCXX23_CONSTEXPR
765 deleter_type&
766 get_deleter() noexcept
767 { return _M_t._M_deleter(); }
768
769 /// Return a reference to the stored deleter.
770 _GLIBCXX23_CONSTEXPR
771 const deleter_type&
772 get_deleter() const noexcept
773 { return _M_t._M_deleter(); }
774
775 /// Return @c true if the stored pointer is not null.
776 _GLIBCXX23_CONSTEXPR
777 explicit operator bool() const noexcept
778 { return get() == pointer() ? false : true; }
779
780 // Modifiers.
781
782 /// Release ownership of any stored pointer.
783 _GLIBCXX23_CONSTEXPR
784 pointer
785 release() noexcept
786 { return _M_t.release(); }
787
788 /** @brief Replace the stored pointer.
789 *
790 * @param __p The new pointer to store.
791 *
792 * The deleter will be invoked if a pointer is already owned.
793 */
794 template <typename _Up,
795 typename = _Require<
796 __or_<is_same<_Up, pointer>,
797 __and_<is_same<pointer, element_type*>,
798 is_pointer<_Up>,
799 is_convertible<
800 typename remove_pointer<_Up>::type(*)[],
801 element_type(*)[]
802 >
803 >
804 >
805 >>
806 _GLIBCXX23_CONSTEXPR
807 void
808 reset(_Up __p) noexcept
809 { _M_t.reset(std::move(__p)); }
810
811 _GLIBCXX23_CONSTEXPR
812 void reset(nullptr_t = nullptr) noexcept
813 { reset(pointer()); }
814
815 /// Exchange the pointer and deleter with another object.
816 _GLIBCXX23_CONSTEXPR
817 void
818 swap(unique_ptr& __u) noexcept
819 {
820 static_assert(__is_swappable<_Dp>::value, "deleter must be swappable");
821 _M_t.swap(__u._M_t);
822 }
823
824 // Disable copy from lvalue.
825 unique_ptr(const unique_ptr&) = delete;
826 unique_ptr& operator=(const unique_ptr&) = delete;
827
828 private:
829#ifdef __glibcxx_out_ptr
830 template<typename, typename, typename...> friend class out_ptr_t;
831 template<typename, typename, typename...> friend class inout_ptr_t;
832#endif
833 };
834
835 /// @{
836 /// @relates unique_ptr
837
838 /// Swap overload for unique_ptr
839 template<typename _Tp, typename _Dp>
840 inline
841#if __cplusplus202002L > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
842 // Constrained free swap overload, see p0185r1
843 _GLIBCXX23_CONSTEXPR
844 typename enable_if<__is_swappable<_Dp>::value>::type
845#else
846 void
847#endif
848 swap(unique_ptr<_Tp, _Dp>& __x,
849 unique_ptr<_Tp, _Dp>& __y) noexcept
850 { __x.swap(__y); }
851
852#if __cplusplus202002L > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11
853 // _GLIBCXX_RESOLVE_LIB_DEFECTS
854 // 2766. Swapping non-swappable types
855 template<typename _Tp, typename _Dp>
856 typename enable_if<!__is_swappable<_Dp>::value>::type
857 swap(unique_ptr<_Tp, _Dp>&,
858 unique_ptr<_Tp, _Dp>&) = delete;
859#endif
860
861 /// Equality operator for unique_ptr objects, compares the owned pointers
862 template<typename _Tp, typename _Dp,
863 typename _Up, typename _Ep>
864 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
865 inline bool
866 operator==(const unique_ptr<_Tp, _Dp>& __x,
867 const unique_ptr<_Up, _Ep>& __y)
868 { return __x.get() == __y.get(); }
869
870 /// unique_ptr comparison with nullptr
871 template<typename _Tp, typename _Dp>
872 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
873 inline bool
874 operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
875 { return !__x; }
876
877#ifndef __cpp_lib_three_way_comparison201907L
878 /// unique_ptr comparison with nullptr
879 template<typename _Tp, typename _Dp>
880 _GLIBCXX_NODISCARD[[__nodiscard__]]
881 inline bool
882 operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
883 { return !__x; }
884
885 /// Inequality operator for unique_ptr objects, compares the owned pointers
886 template<typename _Tp, typename _Dp,
887 typename _Up, typename _Ep>
888 _GLIBCXX_NODISCARD[[__nodiscard__]]
889 inline bool
890 operator!=(const unique_ptr<_Tp, _Dp>& __x,
891 const unique_ptr<_Up, _Ep>& __y)
892 { return __x.get() != __y.get(); }
893
894 /// unique_ptr comparison with nullptr
895 template<typename _Tp, typename _Dp>
896 _GLIBCXX_NODISCARD[[__nodiscard__]]
897 inline bool
898 operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept
899 { return (bool)__x; }
900
901 /// unique_ptr comparison with nullptr
902 template<typename _Tp, typename _Dp>
903 _GLIBCXX_NODISCARD[[__nodiscard__]]
904 inline bool
905 operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept
906 { return (bool)__x; }
907#endif // three way comparison
908
909 /// Relational operator for unique_ptr objects, compares the owned pointers
910 template<typename _Tp, typename _Dp,
911 typename _Up, typename _Ep>
912 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
913 inline bool
914 operator<(const unique_ptr<_Tp, _Dp>& __x,
915 const unique_ptr<_Up, _Ep>& __y)
916 {
917 typedef typename
918 std::common_type<typename unique_ptr<_Tp, _Dp>::pointer,
919 typename unique_ptr<_Up, _Ep>::pointer>::type _CT;
920 return std::less<_CT>()(__x.get(), __y.get());
921 }
922
923 /// unique_ptr comparison with nullptr
924 template<typename _Tp, typename _Dp>
925 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
926 inline bool
927 operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
928 {
929 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
930 nullptr);
931 }
932
933 /// unique_ptr comparison with nullptr
934 template<typename _Tp, typename _Dp>
935 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
936 inline bool
937 operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
938 {
939 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
940 __x.get());
941 }
942
943 /// Relational operator for unique_ptr objects, compares the owned pointers
944 template<typename _Tp, typename _Dp,
945 typename _Up, typename _Ep>
946 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
947 inline bool
948 operator<=(const unique_ptr<_Tp, _Dp>& __x,
949 const unique_ptr<_Up, _Ep>& __y)
950 { return !(__y < __x); }
951
952 /// unique_ptr comparison with nullptr
953 template<typename _Tp, typename _Dp>
954 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
955 inline bool
956 operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
957 { return !(nullptr < __x); }
958
959 /// unique_ptr comparison with nullptr
960 template<typename _Tp, typename _Dp>
961 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
962 inline bool
963 operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
964 { return !(__x < nullptr); }
965
966 /// Relational operator for unique_ptr objects, compares the owned pointers
967 template<typename _Tp, typename _Dp,
968 typename _Up, typename _Ep>
969 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
970 inline bool
971 operator>(const unique_ptr<_Tp, _Dp>& __x,
972 const unique_ptr<_Up, _Ep>& __y)
973 { return (__y < __x); }
974
975 /// unique_ptr comparison with nullptr
976 template<typename _Tp, typename _Dp>
977 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
978 inline bool
979 operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
980 {
981 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(nullptr,
982 __x.get());
983 }
984
985 /// unique_ptr comparison with nullptr
986 template<typename _Tp, typename _Dp>
987 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
988 inline bool
989 operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
990 {
991 return std::less<typename unique_ptr<_Tp, _Dp>::pointer>()(__x.get(),
992 nullptr);
993 }
994
995 /// Relational operator for unique_ptr objects, compares the owned pointers
996 template<typename _Tp, typename _Dp,
997 typename _Up, typename _Ep>
998 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
999 inline bool
1000 operator>=(const unique_ptr<_Tp, _Dp>& __x,
1001 const unique_ptr<_Up, _Ep>& __y)
1002 { return !(__x < __y); }
1003
1004 /// unique_ptr comparison with nullptr
1005 template<typename _Tp, typename _Dp>
1006 _GLIBCXX_NODISCARD[[__nodiscard__]] _GLIBCXX23_CONSTEXPR
1007 inline bool
1008 operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
1009 { return !(__x < nullptr); }
1010
1011 /// unique_ptr comparison with nullptr
1012 template<typename _Tp, typename _Dp>
1013 _GLIBCXX_NODISCARD[[__nodiscard__]] inline bool
1014 operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x)
1015 { return !(nullptr < __x); }
1016
1017#ifdef __cpp_lib_three_way_comparison201907L
1018 template<typename _Tp, typename _Dp, typename _Up, typename _Ep>
1019 requires three_way_comparable_with<typename unique_ptr<_Tp, _Dp>::pointer,
1020 typename unique_ptr<_Up, _Ep>::pointer>
1021 _GLIBCXX23_CONSTEXPR
1022 inline
1023 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer,
1024 typename unique_ptr<_Up, _Ep>::pointer>
1025 operator<=>(const unique_ptr<_Tp, _Dp>& __x,
1026 const unique_ptr<_Up, _Ep>& __y)
1027 { return compare_three_way()(__x.get(), __y.get()); }
1028
1029 template<typename _Tp, typename _Dp>
1030 requires three_way_comparable<typename unique_ptr<_Tp, _Dp>::pointer>
1031 _GLIBCXX23_CONSTEXPR
1032 inline
1033 compare_three_way_result_t<typename unique_ptr<_Tp, _Dp>::pointer>
1034 operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t)
1035 {
1036 using pointer = typename unique_ptr<_Tp, _Dp>::pointer;
1037 return compare_three_way()(__x.get(), static_cast<pointer>(nullptr));
1038 }
1039#endif
1040 /// @} relates unique_ptr
1041
1042 /// @cond undocumented
1043 template<typename _Up, typename _Ptr = typename _Up::pointer>
1044 struct __uniq_ptr_hash
1045 : public __hash_base<size_t, _Up>
1046#if ! _GLIBCXX_INLINE_VERSION0
1047 , private __hash_empty_base<_Ptr>
1048#endif
1049 {
1050 size_t
1051 operator()(const _Up& __u) const
1052 noexcept(noexcept(std::declval<hash<_Ptr>>()(std::declval<_Ptr>())))
1053 { return hash<_Ptr>()(__u.get()); }
1054 };
1055
1056 template<typename _Up>
1057 using __uniq_ptr_hash_base
1058 = __conditional_t<__is_hash_enabled_for<typename _Up::pointer>,
1059 __uniq_ptr_hash<_Up>,
1060 __hash_not_enabled<typename _Up::pointer>>;
1061 /// @endcond
1062
1063 /// std::hash specialization for unique_ptr.
1064 template<typename _Tp, typename _Dp>
1065 struct hash<unique_ptr<_Tp, _Dp>>
1066 : public __uniq_ptr_hash_base<unique_ptr<_Tp, _Dp>>
1067 { };
1068
1069#ifdef __glibcxx_make_unique201304L // C++ >= 14 && HOSTED
1070 /// @cond undocumented
1071namespace __detail
1072{
1073 template<typename _Tp>
1074 struct _MakeUniq
1075 { typedef unique_ptr<_Tp> __single_object; };
1076
1077 template<typename _Tp>
1078 struct _MakeUniq<_Tp[]>
1079 { typedef unique_ptr<_Tp[]> __array; };
1080
1081 template<typename _Tp, size_t _Bound>
1082 struct _MakeUniq<_Tp[_Bound]>
1083 { struct __invalid_type { }; };
1084
1085 template<typename _Tp>
1086 using __unique_ptr_t = typename _MakeUniq<_Tp>::__single_object;
1087 template<typename _Tp>
1088 using __unique_ptr_array_t = typename _MakeUniq<_Tp>::__array;
1089 template<typename _Tp>
1090 using __invalid_make_unique_t = typename _MakeUniq<_Tp>::__invalid_type;
1091}
1092 /// @endcond
1093
1094 /** Create an object owned by a `unique_ptr`.
1095 * @tparam _Tp A non-array object type.
1096 * @param __args Constructor arguments for the new object.
1097 * @returns A `unique_ptr<_Tp>` that owns the new object.
1098 * @since C++14
1099 * @relates unique_ptr
1100 */
1101 template<typename _Tp, typename... _Args>
1102 _GLIBCXX23_CONSTEXPR
1103 inline __detail::__unique_ptr_t<_Tp>
1104 make_unique(_Args&&... __args)
1105 { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
1106
1107 /** Create an array owned by a `unique_ptr`.
1108 * @tparam _Tp An array type of unknown bound, such as `U[]`.
1109 * @param __num The number of elements of type `U` in the new array.
1110 * @returns A `unique_ptr<U[]>` that owns the new array.
1111 * @since C++14
1112 * @relates unique_ptr
1113 *
1114 * The array elements are value-initialized.
1115 */
1116 template<typename _Tp>
1117 _GLIBCXX23_CONSTEXPR
1118 inline __detail::__unique_ptr_array_t<_Tp>
1119 make_unique(size_t __num)
1120 { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); }
9
Calling 'operator new[]'
1121
1122 /** Disable std::make_unique for arrays of known bound.
1123 * @tparam _Tp An array type of known bound, such as `U[N]`.
1124 * @since C++14
1125 * @relates unique_ptr
1126 */
1127 template<typename _Tp, typename... _Args>
1128 __detail::__invalid_make_unique_t<_Tp>
1129 make_unique(_Args&&...) = delete;
1130
1131#if __cplusplus202002L > 201703L
1132 /** Create a default-initialied object owned by a `unique_ptr`.
1133 * @tparam _Tp A non-array object type.
1134 * @returns A `unique_ptr<_Tp>` that owns the new object.
1135 * @since C++20
1136 * @relates unique_ptr
1137 */
1138 template<typename _Tp>
1139 _GLIBCXX23_CONSTEXPR
1140 inline __detail::__unique_ptr_t<_Tp>
1141 make_unique_for_overwrite()
1142 { return unique_ptr<_Tp>(new _Tp); }
1143
1144 /** Create a default-initialized array owned by a `unique_ptr`.
1145 * @tparam _Tp An array type of unknown bound, such as `U[]`.
1146 * @param __num The number of elements of type `U` in the new array.
1147 * @returns A `unique_ptr<U[]>` that owns the new array.
1148 * @since C++20
1149 * @relates unique_ptr
1150 */
1151 template<typename _Tp>
1152 _GLIBCXX23_CONSTEXPR
1153 inline __detail::__unique_ptr_array_t<_Tp>
1154 make_unique_for_overwrite(size_t __num)
1155 { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]); }
1156
1157 /** Disable std::make_unique_for_overwrite for arrays of known bound.
1158 * @tparam _Tp An array type of known bound, such as `U[N]`.
1159 * @since C++20
1160 * @relates unique_ptr
1161 */
1162 template<typename _Tp, typename... _Args>
1163 __detail::__invalid_make_unique_t<_Tp>
1164 make_unique_for_overwrite(_Args&&...) = delete;
1165#endif // C++20
1166
1167#endif // C++14 && HOSTED
1168
1169#if __cplusplus202002L > 201703L && __cpp_concepts202002 && _GLIBCXX_HOSTED1
1170 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1171 // 2948. unique_ptr does not define operator<< for stream output
1172 /// Stream output operator for unique_ptr
1173 /// @relates unique_ptr
1174 /// @since C++20
1175 template<typename _CharT, typename _Traits, typename _Tp, typename _Dp>
1176 inline basic_ostream<_CharT, _Traits>&
1177 operator<<(basic_ostream<_CharT, _Traits>& __os,
1178 const unique_ptr<_Tp, _Dp>& __p)
1179 requires requires { __os << __p.get(); }
1180 {
1181 __os << __p.get();
1182 return __os;
1183 }
1184#endif // C++20 && HOSTED
1185
1186#if __cpp_variable_templates201304L
1187 template<typename _Tp>
1188 constexpr bool __is_unique_ptr = false;
1189 template<typename _Tp, typename _Del>
1190 constexpr bool __is_unique_ptr<unique_ptr<_Tp, _Del>> = true;
1191#endif
1192
1193 /// @} group pointer_abstractions
1194
1195#if __cplusplus202002L >= 201703L
1196 namespace __detail::__variant
1197 {
1198 template<typename> struct _Never_valueless_alt; // see <variant>
1199
1200 // Provide the strong exception-safety guarantee when emplacing a
1201 // unique_ptr into a variant.
1202 template<typename _Tp, typename _Del>
1203 struct _Never_valueless_alt<std::unique_ptr<_Tp, _Del>>
1204 : std::true_type
1205 { };
1206 } // namespace __detail::__variant
1207#endif // C++17
1208
1209_GLIBCXX_END_NAMESPACE_VERSION
1210} // namespace
1211
1212#endif /* _UNIQUE_PTR_H */

←

/root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/mozilla/cxxalloc.h

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5#ifndef mozilla_cxxalloc_h
6#define mozilla_cxxalloc_h
7
8/*
9 * We implement the default operators new/delete as part of
10 * libmozalloc, replacing their definitions in libstdc++. The
11 * operator new* definitions in libmozalloc will never return a NULL
12 * pointer.
13 *
14 * Each operator new immediately below returns a pointer to memory
15 * that can be delete'd by any of
16 *
17 * (1) the matching infallible operator delete immediately below
18 * (2) the matching system |operator delete(void*, std::nothrow)|
19 * (3) the matching system |operator delete(void*) noexcept(false)|
20 *
21 * NB: these are declared |noexcept(false)|, though they will never
22 * throw that exception. This declaration is consistent with the rule
23 * that |::operator new() noexcept(false)| will never return NULL.
24 *
25 * NB: mozilla::fallible can be used instead of std::nothrow.
26 */
27
28#ifndef MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline
29# define MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline MFBT_API__attribute__((weak)) __attribute__((visibility("default")))
30#endif
31
32MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new(size_t size) noexcept(false) {
33 return moz_xmalloc(size);
34}
35
36MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new(size_t size,
37 const std::nothrow_t&) noexcept(true) {
38 return malloc_implmalloc(size);
39}
40
41MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new[](size_t size) noexcept(false) {
42 return moz_xmalloc(size);
10
Value of 'errno' was not checked and may be overwritten by function 'moz_xmalloc'
43}
44
45// Inlining `new` like this is technically against C++ spec, but we crave perf.
46MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void* operator new[](size_t size,
47 const std::nothrow_t&) noexcept(true) {
48#if defined(__GNUC__4) && !defined(__clang__1)
49// GCC-14 codegen at -O2 causes false positive due to converting
50// `new A[n]` to `malloc(-1)` when `n > PTRDIFF_MAX/sizeof(A)`.
51// (See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85783, WONTFIX'd)
52# pragma GCC diagnostic push
53# pragma GCC diagnostic ignored "-Walloc-size-larger-than="
54#endif
55
56 return malloc_implmalloc(size);
57
58#if defined(__GNUC__4) && !defined(__clang__1)
59# pragma GCC diagnostic pop
60#endif
61}
62
63MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr) noexcept(true) {
64 return free_implfree(ptr);
65}
66
67MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr,
68 const std::nothrow_t&) noexcept(true) {
69 return free_implfree(ptr);
70}
71
72MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](void* ptr) noexcept(true) {
73 return free_implfree(ptr);
74}
75
76MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](
77 void* ptr, const std::nothrow_t&) noexcept(true) {
78 return free_implfree(ptr);
79}
80
81#if defined(XP_WIN)
82// We provide the global sized delete overloads unconditionally because the
83// MSVC runtime headers do, despite compiling with /Zc:sizedDealloc-
84MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete(void* ptr,
85 size_t /*size*/) noexcept(true) {
86 return free_implfree(ptr);
87}
88
89MOZALLOC_EXPORT_NEW__attribute__((always_inline)) inline void operator delete[](void* ptr,
90 size_t /*size*/) noexcept(true) {
91 return free_implfree(ptr);
92}
93#endif
94
95#endif /* mozilla_cxxalloc_h */